React Context
A built-in way to pass a value to deep components without props.
Ideal for rarely changing values like theme or auth; frequent updates re-render all consumers.
State & data fetching
Context passes values down the tree but re-renders every consumer on change; Zustand and Redux keep state in an external store and let components subscribe to just the slice they need.
A built-in way to pass a value to deep components without props.
Ideal for rarely changing values like theme or auth; frequent updates re-render all consumers.
A small external store with hook-based selectors.
Components re-render only when their selected slice changes; minimal API.
A single external store updated through actions and reducers.
Structured, traceable updates with DevTools and middleware for large apps.
| Aspect | React Context | Zustand | Redux (Toolkit) |
|---|---|---|---|
| Built in | Yes | No | No |
| Re-render control | All consumers | Selector-based | Selector-based |
| Boilerplate | Low | Very low | Medium with RTK |
| DevTools | React DevTools | Redux DevTools via middleware | Redux DevTools |
| Use for | Theme, locale, auth user | App state in small/mid apps | Complex shared state, big teams |
Context passes a value down the tree without props, but every consumer re-renders when that value changes. Zustand and Redux keep state in an external store and let components subscribe to only the slice they select, so updates re-render fewer components.
Not by itself. Context is a transport for values; state still lives in useState or useReducer in a provider. It works well for values that change rarely.
For rarely changing, app-wide values such as theme, locale, current user or feature flags, and for dependency injection of services into a subtree.
When state updates often and many components consume it, causing broad re-renders, or when you need selectors, middleware, persistence or DevTools.
With Context, all components using the context re-render on any change to its value. With Zustand or Redux selectors, only components whose selected data changed re-render.
Split contexts by concern, memoise the provided value, separate state and dispatch into different contexts, and keep frequently changing values out of broad contexts.
Context needs a createContext, a provider component and a hook. Zustand needs one create() call. Redux Toolkit needs slices, a store and a Provider.
With Context, async code lives in provider functions or hooks. Zustand actions can be async. Redux uses thunks, createAsyncThunk or RTK Query.
React DevTools shows Context values. Redux DevTools shows Redux actions and state history, and Zustand can connect to Redux DevTools with middleware.
Redux needs a Provider at the top of the tree. Zustand stores are hooks that work without providers, though you can use context for per-request stores in SSR.
Practise every comparison in your dashboard.
Start learning