React Context provides a way to pass data through the component tree without prop drilling. Combined with the useReducer hook, it offers a lightweight alternative to Redux for global state management. However, misuse can lead to performance issues.
The Split Context Pattern
To avoid unnecessary re-renders, split State and Dispatch into separate contexts.
const StateContext = createContext();
const DispatchContext = createContext();
export function UserProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
{children}
</DispatchContext.Provider>
</StateContext.Provider>
);
}
// Custom Hooks for consumption
export const useUserState = () => useContext(StateContext);
export const useUserDispatch = () => useContext(DispatchContext);
Why Split?
Components that only need to trigger actions (like a generic button) can consume DispatchContext without re-rendering when the state changes.
Key Takeaways
- Context is not optimized for high-frequency updates (use Recoil or Jotai for that).
- Always memoize the `value` prop if it’s an object.
- Place Providers as low in the tree as possible to limit scope.
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.