将状态和调度放入单独的上下文提供程序中是否可以防止不必要的重新渲染?
Does putting state and dispatch into separate context providers prevent unnecessary re-renders?
我发现在 official next.js example、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>
)
}
编辑:
正如@dciccale 在评论中指出的那样,如果您的应用程序中有相当多的组件主要只使用调度,那么将调度和状态保持在不同的上下文中很有意义,因此它们不会重新调用-如果状态改变则渲染。
即使我们用 useMemo hook 记住了 contextValue
,每次更新 state
的值时,contextValue
仍然会重新计算,导致所有依赖于上下文的组件重新渲染,甚至其中一些只依赖于 dispatch
only.
另请参阅:https://hswolff.com/blog/how-to-usecontext-with-usereducer/#performance-concerns
评估您的应用要求并做出明智的决定。
我发现在 official next.js example、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>
)
}
编辑:
正如@dciccale 在评论中指出的那样,如果您的应用程序中有相当多的组件主要只使用调度,那么将调度和状态保持在不同的上下文中很有意义,因此它们不会重新调用-如果状态改变则渲染。
即使我们用 useMemo hook 记住了 contextValue
,每次更新 state
的值时,contextValue
仍然会重新计算,导致所有依赖于上下文的组件重新渲染,甚至其中一些只依赖于 dispatch
only.
另请参阅:https://hswolff.com/blog/how-to-usecontext-with-usereducer/#performance-concerns
评估您的应用要求并做出明智的决定。