React Context vs Redux: When to Use Which
A practical comparison of React Context and Redux: rendering model, performance, devtools, and concrete heuristics for picking the right tool.
What you'll learn
- ✓What Context is actually designed for
- ✓How Redux differs as a state container
- ✓Re-render behavior of each approach
- ✓Performance tradeoffs in real apps
- ✓How to choose between them
Prerequisites
- •Comfortable with React hooks
“Should I use Context or Redux?” is one of the most repeated React questions, and the answer is usually “neither alone, and not for what you think.” Context is a dependency-injection mechanism, not a state manager. Redux is a state container with strict update rules. They solve overlapping but different problems, and you can use both in the same app without contradiction.
What and why
React Context lets a parent provide a value that any descendant can read, regardless of how deep the tree gets. It exists to avoid prop drilling. When the provider’s value changes, every consumer re-renders. There is no built-in selector, no diffing, no middleware. You hand it a value, and React broadcasts it.
Redux is a predictable state container. State lives in a single store. You dispatch actions, a reducer returns the new state, and components subscribe via selectors. React-Redux only re-renders a component when its selected slice changes. Redux Toolkit (RTK) is the modern flavor and removes most of the historical boilerplate.
Mental model
Context is a tube: anything you pour in at the top reaches anyone reading from it. Redux is a database: components query it and only react when their query result changes.
Context:
Provider value changes
|
v
All consumers re-render (no selector filtering)
Redux:
dispatch(action)
|
v
Reducer returns new state
|
v
Only components whose selector result changed re-render The practical implication: if you put a frequently-updating value into Context, every consumer renders on every change. With Redux, only consumers whose selected slice changed will render.
Hands-on example
A theme toggle is a textbook Context use case: rarely changes, read everywhere.
const ThemeContext = createContext<'light' | 'dark'>('light');
function App() {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
return (
<ThemeContext.Provider value={theme}>
<button onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}>
Toggle
</button>
<Page />
</ThemeContext.Provider>
);
}
function Page() {
const theme = useContext(ThemeContext);
return <div className={theme}>...</div>;
}
A shopping cart with many slices and frequent updates is a better fit for Redux:
// store/cartSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
type Item = { id: string; qty: number };
const cartSlice = createSlice({
name: 'cart',
initialState: { items: [] as Item[] },
reducers: {
add(state, action: PayloadAction<Item>) {
const existing = state.items.find(i => i.id === action.payload.id);
if (existing) existing.qty += action.payload.qty;
else state.items.push(action.payload);
},
remove(state, action: PayloadAction<string>) {
state.items = state.items.filter(i => i.id !== action.payload);
},
},
});
export const { add, remove } = cartSlice.actions;
export default cartSlice.reducer;
function CartCount() {
const count = useSelector((s: RootState) => s.cart.items.length);
return <span>{count}</span>;
}
CartCount only re-renders when the item count changes, not when quantities of existing items mutate. That granularity is the value Redux adds.
Common pitfalls
- Putting changing values into Context without memoizing them. Every parent render creates a new object identity, even if the contents are the same, which causes consumer re-renders.
- Wrapping the entire app in a single giant Context that holds dozens of unrelated fields. Splitting Context by domain is almost always better.
- Reaching for Redux for a tiny piece of UI state. A
useStatein a parent is fine for most local concerns. - Using selectors that return new arrays or objects on each call. Without a shallow or deep equality check, you trigger unnecessary re-renders.
Best practices
- Context for: theme, locale, auth user, current route, feature flags. Things that change rarely and are read widely.
- Redux for: domain state that many components write to and read from, derived data, undo/redo, and time-travel debugging.
- Use multiple small contexts instead of one large one. Group values that change together.
- For Redux, always use Redux Toolkit. The hand-written switch statements and action constants are no longer required.
- If you need cross-component state without Redux, consider Zustand or Jotai. They give you selector-based subscriptions without the Redux scaffolding.
FAQ
Does Context make the app slower? Only if you push high-frequency updates through it. For static-ish values it’s fine.
Can I use both? Yes, and most large apps do. Auth and theme in Context; domain data in Redux or Zustand.
Is Redux dead? No. RTK and RTK Query are very much alive and remain the default at many large companies because of their debugging story and middleware ecosystem.
What about React’s use() and Server Components? Server data fetched with use() lives outside Redux. You typically use Redux for client-side mutations and Server Components for read-paths.
Related articles
- React React State Management: Zustand vs Redux vs Context Compared
Compare Zustand, Redux Toolkit, and React Context for state management. Learn when each shines, their trade-offs, and how to pick the right tool.
- React useReducer in React and Why It Beats useState Sometimes
Understand React's useReducer hook, its signature, action shape, when to migrate from useState, and how to build a small state machine pattern for predictable UI logic.
- React Zustand: Minimal State Management for React
Skip the reducer boilerplate. Zustand gives React apps a tiny global store with hooks, selectors, and middleware in fewer than 100 lines of API.
- JavaScript React Context API Guide
Learn how to use React's Context API to share state across your component tree without prop drilling — with patterns, performance tips, and common mistakes to avoid.