将状态和调度放到单独的上下文提供程序中是否可以防止不必要的重新呈现



我发现在官方的next.js示例中,statedispatch是独立的上下文提供者。

这样做有什么意义?这种做法是否可以防止不必要的重新渲染?

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)

如果几乎所有组件都同时使用state和dispatch,则不需要将它们放在单独的ContextProviders中,只需确保在将它们作为对象传递时,将传递给提供程序值的参数存储在内存中即可。这样,只有当状态实际发生变化时,消费者才会重新呈现。还要注意,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>
)
}

编辑:

正如@dciccale在评论中指出的那样,如果你的应用程序中有很多组件主要只使用调度,因此如果状态发生变化,它们不会重新呈现,那么将调度和状态保持在不同的上下文中是非常有意义的。

即使我们用useMemo钩子记住contextValue,每次更新state的值时,contextValue仍然会被重新求值,导致所有依赖于上下文的组件都被重新调用,甚至有些组件只依赖于dispatch

另请参阅:https://hswolff.com/blog/how-to-usecontext-with-usereducer/#performance-涉及

评估您的应用程序需求并明智地做出决定。

最新更新