← Back to blog

Context API vs Redux

3 min read
#react#redux#context#state-management

The question is usually framed as "which one is better", but that's the wrong question. Context and Redux do different jobs. The important part is understanding how each one updates its consumers.

👉 Try it in practice: Shopping Cart with Context

What Context actually does

Context lets a component read and subscribe to a value without threading it down through props. The context object itself does not hold data; it only describes what can be provided and read. To make the value change, you pair the provider with useState or useReducer.

const ThemeContext = createContext("light");

function App() {
  const [theme, setTheme] = useState("light");
  return (
    <ThemeContext value={theme}>
      <Page />
    </ThemeContext>
  );
}

The key detail, from the React docs: when the value you pass to a provider changes, React re-renders every component that reads that context. It compares the old and new values with Object.is. There are no selectors, so you can't subscribe to just one field of the value.

What Redux adds

Redux is a centralized store with a single flow: action, reducer, store. Around that flow you get middleware, Redux DevTools, and an action history, so you can answer "when did this slice change and where did the data come from?".

Its real advantage over Context is useSelector. A component subscribes to the result it selects, not to the whole store:

const count = useSelector((s) => s.cart.items.length);
const theme = useSelector((s) => s.theme.mode);

Change cart and the component reading theme does not re-render. With Context, it would.

The re-render difference

A Context subscription is to the context value as a whole, not to individual fields. Put { user, cart, theme } in a single context and changing cart re-renders the component that only reads theme too. You can fix this by splitting into multiple contexts and memoizing values, but that's work you do by hand. Redux gives you granular subscriptions through selectors.

When to use each

Context for simple shared values with few consumers: theme, locale, current user, and state scoped to one feature. Zero dependencies.

Redux when shared client state gets large, is used in many places, or has update logic that's getting complex. It also helps when you need to inspect how state changes over time with Redux DevTools.

Data fetched from an API is server state and belongs in SWR or React Query, not in either of these.

A real example: the shopping cart

A cart with a few items, a header badge, and a checkout button is fine in Context.

Watch what happens as it grows: a coupon field, a quantity stepper, a "save for later" list. Now items, coupon, and saved share one context. Updating items re-renders the coupon and saved consumers too. Put the coupon draft in that same context and every keystroke re-renders the header badge.

That's where selectors earn their keep: components can subscribe to different slices of state independently, and a component re-renders only when the piece it reads changes. Redux DevTools and action history are the bonus on top.

Start with Context. Reach for a store when the state and its consumers get complex enough to justify it, not before.

👉 Build both and compare: Shopping Cart with Redux Toolkit

Put what you read into practice