javascript - React.memo and shallow comparision
问题描述
I was reading the following article on React.memo https://blog.bitsrc.io/optimize-your-react-app-with-react-memo-ec52447b09ba
I had 2 specific questions around the article.
- As per the link, it says "In function components React only performs two optimizations by default. First, it avoid the re-render process if by shallow comparison the new state is equal to the old state. Second, it only updates the DOM nodes which have changed and not the whole DOM as updating DOM is costly."
I was confused when it says React by default, compares the state. My understanding is that happens only if we use React.memo. Am I missing something here ?
- As per the Shallow Comparison example shown on the site, it seems to suggest different behavior for objects v/s arrays. Not sure if that is correct as well. I thought both arrays/objects would get a new reference each time and hence shallow comparison would return false every time for them ?
Specifically, this example on the link confused me;
const car1 = {
color: 'red',
model: 'S',
};
const car2 = {
color: 'red',
model: 'X',
};
const car3 = {
color: 'red',
model: 'S',
};
shallowCompare(car1, car2); // false
shallowCompare(car1, car3); // true - Why would this return true ???
const arr1 = [1];
const arr2 = [1];
const arr3 = arr1;
console.log(arr1 === arr2); // false - Why is this different compared to object behavior ?
console.log(arr1 === arr3); // true
Also, from my end I tried using below custom function for shallow compare and observed both object and array to behave similarly. This function is not part of the article link above.
function areEqualShallow(a, b) {
for(var key in a) {
if(!(key in b) || a[key] !== b[key]) {
return false;
}
}
for(var key in b) {
if(!(key in a) || a[key] !== b[key]) {
return false;
}
}
return true;
}
解决方案
让我们从一个事实开始,最可靠的来源是 React 团队发布的内容。
当它说 React 默认情况下比较状态时,我感到很困惑。我的理解是,只有当我们使用 React.memo 时才会发生这种情况。我在这里错过了什么吗?
确实,您无法自定义在 React 中比较状态的方式。
尽管有一些解决方法,但他们不考虑“默认情况下”,例如通过将先前的状态保存在引用中并通过它有条件地更改状态:
useEffect(() => {
if (areEqualCustom(prevState.current, newState)) {
setState(newState);
prevState.current = newState;
}
}, [newState]);
根据网站上显示的浅比较示例,它似乎暗示了对象与数组的不同行为。也不确定这是否正确。我认为两个数组/对象每次都会获得一个新的引用,因此每次浅比较都会为它们返回 false?
你是对的,作者对“浅比较”的定义是错误的,因为“浅比较”是由严格等式(===
)运算符定义的。
// Blog example
const car1 = {
color: 'red',
model: 'S',
};
const car3 = {
color: 'red',
model: 'S',
};
// car1 === car3
shallowCompare(car1, car3) // always false
// React example
const onClick = () => {
// Don't mutate state in React.
stateObject.x = 5;
// prevState === stateObject (true)
setState(stateObject); // no render
// Instead use Object.assign / shallow copy
setState({ ...stateObject, x: 5 }); // always render
};
请注意,在最后一个示例中,即使先前状态和当前状态非常相等,它仍然会重新渲染。
setState({ x: 5 }); // always render
// even if prevState = { x: 5 }
[1] === [1]
为什么这与对象行为不同?
这不是,这是相同的行为。
推荐阅读
- botframework - 通过bot framework composer发送http请求文件
- javascript - 如何使用 vanilla JavaScript 在 Django 而不是 Jquery 上添加 ajax 请求
- css - React JS 中的 overflow-x 和 flex-wrap 有什么问题?
- android - kotlin 程序编译期间的房间数据库错误
- haskell - 澄清有关 Haskell 类型系统的术语
- html - 如何为 RTL 用户转换 jquery pic zoomer
- python - 如何过滤掉架构中的某些元素
- python - 找到匹配项时,将相应的值写入匹配列旁边
- python - AttributeError:“字节”对象没有属性“getPage”
- python - 使用熊猫将列作为日期从长到宽