Does putting state and dispatch into separate context providers prevent unnecessary re-renders?
Asked Answered
F

1

10

I found that in the official next.js example, state and dispatch were put info separate context providers.

What was the point of doing so? Does this practice prevent unnecessary re-renders?

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)
Fragonard answered 24/3, 2021 at 7:46 Comment(0)
A
14

You do not need to put them in separate ContextProviders if almost all of your components are using both state and dispatch, just make sure that you are memoizing the argument you pass to the provider value when you pass them as a object. This way your consumers will only re-render when state actually changes. Also note that dispatch instance doesn't actually change so there is no point in creating aa separate context for it

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>
  )
}

EDIT:

As @dciccale pointed out in the comments, it makes a lot of sense to keep dispatch and state in separate contexts if there are quite a lot of components in your app which largely only use dispatch and hence they will not re-render if state changes.

Even if we memorize contextValue with useMemo hook, contextValue will still be re-evaluated every time we update state's value, causing all components depending on the context to rerender, even some of them only depend on dispatch only.

See also: https://hswolff.com/blog/how-to-usecontext-with-usereducer/#performance-concerns

Evaluate your app requirements and take a decision wisely.

Arlo answered 24/3, 2021 at 7:52 Comment(4)
Is there any benefit to have two separated context providers? Or it is just next.js authers over-engineered their example?Fragonard
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 purposeArlo
I can't find any guide about separating context in Google. Can you explain more?Fragonard
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.Unprecedented

© 2022 - 2024 — McMap. All rights reserved.