reselect 的 createSelector:是否对嵌套对象进行深度比较?

createSelector of reselect: does it do deep comparison for nested object?

如果 second(nested object) 在 redux 中发生变化怎么办? 如果它进行浅比较,它应该忽略更改而不是重新渲染。

我在文档中看到的所有示例,它们都是基于一个简单的对象,浅比较是可以的。

// assume state is:  {data: {first : {second { } } }}

const selectData = state => state.data;

const selectSecond = createSelector(
    selectData,
    data => data
);

createSelector使用strict equality (===),这意味着两个对象当且仅当它们是对内存中同一对象的引用时才被认为是“相等的”。这与 React 在比较 state 或比较 useEffect 依赖项时使用的检查类型相同。

浅相等意味着两个对象相等,如果它们的所有属性都严格相等。

深度相等意味着如果两个对象的内容相同,则它们相等,而不管对象引用如何。由于数据的不可变特性,它在计算上非常昂贵,在 React 或 Redux 中几乎不需要。


Redux 状态被认为是不可变的,因此您永远不会遇到对象在内存中是相同引用但具有不同内容的情况。每次 属性 发生变化时,您都必须创建一个新对象。如果 second 已更改,则 firstdata 将是新对象。

What if 'second' (nested object) change in redux? If it do shallow comparison it should ignore the change and not rerender.

只有在您的状态发生突变时,您才会遇到这个问题。只要你的减速器是正确的,那么只要 state.data 发生变化,你就会得到重新渲染,因为任何变化都需要创建一个新对象。


以下是各种相等性检查的几个示例:

state => state

state是严格相等,浅相等,深相等。

state => ({...state})

state是浅相等,深相等。它不是严格相等的,因为它是一个新对象。

state => ({...state, nested: {...state.nested}})

state 深等。它不是严格相等或浅相等,因为 nested 属性 是一个新对象。

state => ({...state, number: 5})

state 已更改 属性,因此它无法通过所有相等性检查。

state => {
  state.nested.number = 5;
  return state;
}

这种突变在 React 或 Redux 中是不允许的。 state 是严格相等的,因为我们返回了相同的 state 对象。它也是浅相等的,因为 state.nested 是同一个对象。它不是深度相等(除非之前的值为 5)。

state => {
  state.nested = 5;
  return state;
}

同样,这是不允许的。如果您改变顶级 属性,那么 state 是严格相等的,但不是浅相等或深相等。