React Context Best Practices and Patterns

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.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.