首页 > 解决方案 > 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.

  1. 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 ?

  1. 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;
}

标签: javascriptreactjs

解决方案


让我们从一个事实开始,最可靠的来源是 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]为什么这与对象行为不同?

这不是,这是相同的行为。


推荐阅读