How To Set Up React Context

Prop drilling ruins your code. You pass data through five layers of components that do not need it. React Context fixes this. However, most setups create a new problem.

When you use "Go to Definition" on a context hook, you often land in a file with nothing but a tiny useContext call. The actual logic lives in a different file. You spend your day searching for state logic.

You can fix this with a better structure.

Follow this pattern:

  • Put the context, the public hook, and the state logic in one file.
  • Keep the Provider as a thin shell.
  • Use a lint rule to protect your private logic.

Structure your files like this:

src/context/ • GameContext.ts (Context, public hook, and state logic) • GameProvider.tsx (A thin shell)

Inside GameContext.ts, create three parts:

  1. The context object.
  2. A public hook for components to use. This hook should throw an error if the context is null. This ensures your components fail fast if they are outside the provider.
  3. A private hook for state management. This hook contains your useState or useReducer calls.

By putting the public hook and the private logic in the same file, "Go to Definition" works perfectly. You jump directly from the component to the logic.

One risk exists. Because the private hook is exported so the Provider can use it, a teammate might call it in the wrong place. If they do, they create a new, isolated state instead of using the shared context.

Stop using comments to prevent this. Use an ESLint rule instead.

I created eslint-plugin-restrict-callers to solve this. You can define which functions are allowed to call specific hooks.

For example, you can tell ESLint that only GameProvider can call useGameStateManagement. If anyone else tries, the build fails with a clear error message.

Summary of the workflow:

  • Group context, public hooks, and private logic in one file.
  • Use the Provider only to pass the hook result to the provider value.
  • Throw errors in the public hook if context is missing.
  • Use ESLint to enforce boundaries between public and private hooks.

Source: https://dev.to/jareddlewis/how-to-set-up-react-context-2c9h