重新选择的createSelector:它是否对嵌套对象进行深度比较?

use*_*135 2 reactjs react-redux reselect

如果second(嵌套对象)在 redux 中发生变化怎么办?如果它进行浅比较,它应该忽略更改并且不重新渲染。

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

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

const selectData = state => state.data;

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

Run Code Online (Sandbox Code Playgroud)

Lin*_*ste 8

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

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

深度相等意味着如果两个对象的内容相同,则无论对象引用如何,它们都是相等的。由于数据的不可变性质,它的计算成本很高,并且在 React 或 Redux 中几乎不需要。


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

如果 redux 中的“第二个”(嵌套对象)发生变化怎么办?如果它进行浅比较,它应该忽略更改并且不重新渲染。

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


以下是各种相等性检查的一些示例:

state => state
Run Code Online (Sandbox Code Playgroud)

state是严格平等、浅度平等、深度平等。

state => ({...state})
Run Code Online (Sandbox Code Playgroud)

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

state => ({...state, nested: {...state.nested}})
Run Code Online (Sandbox Code Playgroud)

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

state => ({...state, number: 5})
Run Code Online (Sandbox Code Playgroud)

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

state => {
  state.nested.number = 5;
  return state;
}
Run Code Online (Sandbox Code Playgroud)

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

state => {
  state.nested = 5;
  return state;
}
Run Code Online (Sandbox Code Playgroud)

这又是不允许的。如果您改变顶级属性,则state严格相等,但不是浅相等或深度相等。