将状态和分派放入单独的上下文提供程序是否可以防止不必要的重新渲染?
我在官方的 next.js 示例中发现了这一点,state并且dispatch将信息放在了单独的上下文提供程序中。
这样做的意义何在?这种做法是否可以防止不必要的重新渲染?
export const CounterProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, 0)
return (
<CounterDispatchContext.Provider value={dispatch}>
<CounterStateContext.Provider value={state}>
{children}
</CounterStateContext.Provider>
</CounterDispatchContext.Provider>
)
}
export const useCount = () => useContext(CounterStateContext)
export const useDispatchCount = () => useContext(CounterDispatchContext)
回答
如果几乎所有组件都同时使用状态和分派,则不需要将它们放在单独的 ContextProvider 中,只需确保在将它们作为对象传递时记住传递给提供程序值的参数。这样你的消费者只会在状态实际改变时重新渲染。还要注意,dispatch实例实际上并没有改变,所以没有必要为它创建一个单独的上下文
export const CounterProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, 0)
const contextValue = useMemo(() => ({state, dispatch}), [state, dispatch])
return (
<CounterContext.Provider value={contextValue}>
{children}
</CounterContext.Provider>
)
}
编辑:
正如@dcccale 在评论中指出的那样,如果您的应用程序中有很多组件在很大程度上只使用 dispatch 并且因此它们不会在状态更改时重新渲染,那么将 dispatch 和 state 保持在单独的上下文中是很有意义的.
即使我们contextValue用 useMemo hook记忆,contextValue每次更新state的值仍然会被重新评估,导致所有依赖于上下文的组件重新渲染,甚至其中一些只依赖于dispatchonly。
另见:https : //hswolff.com/blog/how-to-usecontext-with-usereducer/#performance-concerns
评估您的应用要求并明智地做出决定。
- I think It *does* make a difference making a separate context provider for the state and for the dispatch. If you have child components that *only* require the dispatch function, and not the state, those components will be re-render as well if the state of the provider changed. however, if there are separate context provider, one for the state and one for the dispatch, child components only using the dispatch won't need to re-render when the state changes.
- There is benefit to separating context when context is storing information of widely different things, inn the above case, its not required and serves non special purpose