我在reducer函数中使用了spread运算符,所以当我调度操作时会发生什么,然后它会创建新状态(obj(——即使旧状态与新状态相同,所以它会重新呈现react组件。
因为对象可能很复杂,所以比较新状态和旧状态是一种好方法吗?深度对比?
const initialState = {};
export const reducer = (state = initialState, action: any = {}): any => {
if (action.type === ActionTypes.RC) {
return {
...state,
...action.config,
};
}
return state;
};
或者redux在mapStateToProps中为您开箱即用?
这里有几点值得注意。
React Redux使用严格相等(引用相等(作为默认的比较方法。Redux状态的不可变特性意味着,对深度嵌套属性的任何更改都要求其所有祖先都必须是新的对象引用。
如果更新a.b.c
,则a
和a.b
必须是新对象。假设您有一个类似a.d.e
的同级属性树。更新a.b.c
时,会使a
成为新的对象引用,但a.d
和a.d.e
是相同的。如果您有一个只需要了解a.d
的组件,那么它就不需要响应a.b.c
的更改而重新渲染。
这就是为什么每个组件都应该只从状态中选择所需的最小信息这一点很重要。您应该连接更多单独的组件,而不是从状态中选择大量信息并通过道具传递。您可以在同一组件中使用多个useSelector
挂钩来选择小的、细粒度的状态块。
您确实可以通过将比较函数作为第二个参数传递给useSelector
钩子来自定义相等比较。
如果您有一个订阅由该reducer控制的状态块的组件,那么您可以使用react-redux
包中包含的shallowEqual
函数。我不确定你的问题中的reducer是你的根reducer还是你传递给combineReducers
的东西。我想这只是一部分。假设它用于属性settings
,并且您有一些updateSettings
操作将新设置与现有设置合并。然后,当你有一个组件需要访问设置时,你会这样做:
import { shallowEqual, useSelector } from 'react-redux'
const settings = useSelector(state => state.settings, shallowEqual);
这意味着,即使state.settings
是一个新对象,只有在某些设置实际发生更改的情况下,组件才会重新渲染。它正在对CCD_ 19的当前值和以前的值进行浅层比较。
可以使用像lodash的isEqual
这样的深度相等比较,但我不明白你为什么需要它,因为这个减速器正在进行浅层复制。如果您需要在任何地方进行昂贵的检查,那么在dispatch
组件中的操作之前或在从reducer返回新对象之前进行检查似乎更合乎逻辑,而不是在useSelector
钩子的每次调用中进行检查。
您询问在返回新的state
对象之前是否应该检查reducer中的更改。这是个好主意,实际上combineReducers
创建的组合减速器就是这样做的,尽管它只检查浅相等性。请参阅源代码的第177-201行。如果所有单独的属性还原器都返回了与以前相同的对象,那么它将返回以前组合的state
,以维护对象引用。
个人意见:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);// <= re-render state diff here
页面是否应该重新渲染由反应决定,或者说:会更好。
反应中有dom-diff algorithm
。
您从多个页面调度操作,这些页面从newState中选择自己的状态,并对自己进行差异,触发是否重新呈现。
所以我认为你不必在减速器中运行另一个diff algorithm
。
考虑案例:
您有PageA&PageAB,状态{a:1,b:1}
PageA由a重新渲染PageAB由a,b 重新渲染
现在您的状态变为{a:1,b:2}。如何使PageA不在reducer
中重新呈现?您将在PageA中对其进行区分。