Redux vs React Context

"Should we use Redux or Context?" is one of the most common React architecture questions — and it compares two different kinds of tools. React Context is a mechanism for passing a value down the component tree without threading props through every level. It does not manage state by itself; whatever state you put in it still lives in useState or useReducer somewhere. Redux (in its modern form, Redux Toolkit) is a state management library: a single store outside React, updated by dispatched actions through reducers, with selective subscriptions, middleware, and powerful developer tools.

Short verdict: use Context for values that change rarely and are needed widely — theme, locale, the current user, feature flags, dependency injection. Use Redux Toolkit (or a lighter store such as Zustand) for complex, frequently updated client state shared across many components. Use a server-state library for data from APIs, whichever you choose. Most "Redux vs Context" debates disappear once server state moves to TanStack Query or RTK Query.

TL;DR

Quick Example

Context is ideal for a rarely changing value such as the theme:

Redux Toolkit suits a frequently updated cart that many components read in different ways:

Core Concepts

Head-to-Head

Why Context Re-Renders

When a provider's value changes — including when it is a new object created on every render — React re-renders every component that reads that context. There is no built-in way to subscribe to just one field. For values that change rarely, this does not matter. For a large object updated on every keystroke, it can re-render much of the app. Mitigations include splitting contexts (state and dispatch separately, or by domain), memoizing the value, and keeping fast-changing state local.

useReducer Plus Context

Combining useReducer with Context gives Redux-like actions and reducers without a library, and works well for a feature-sized slice of state — a multi-step form, a wizard, an editor panel. It still lacks selectors, middleware, and DevTools, and tends to grow awkward as more of the app depends on it.

Redux Toolkit

Modern Redux is Redux Toolkit: configureStore with good defaults, createSlice for reducers and actions with Immer-powered "mutating" updates, createAsyncThunk and listener middleware for side effects, and RTK Query for fetching and caching server data. Much of the boilerplate that gave Redux its reputation is gone. See Redux.

Server State Is a Separate Problem

Lists of projects, user profiles, and search results are server state: owned by the backend, cached on the client, and needing loading states, refetching, invalidation, and deduplication. Libraries built for this — TanStack Query or RTK Query — handle it far better than storing responses in Context or hand-written Redux slices. Once server state moves out, the remaining client state is usually small.

Other Options

The Decision Framework

Best Practices

Start Local, Lift When Needed

Keep state in the component that uses it, lift it to a common parent when siblings need it, and reach for Context or a store only when prop passing becomes painful across distant components.

Split Contexts by Change Frequency

Put rarely changing values and fast-changing values in separate providers, so frequent updates do not re-render every consumer.

Select Narrowly

With Redux or Zustand, select the smallest data a component needs and derive values with memoized selectors.

Keep Server State Out of Client Stores

Use a server-state library for API data. Duplicating responses into Redux or Context invites stale data and manual cache invalidation.

Common Mistakes

One Giant Context

Redux for Everything

New Context Values on Every Render

FAQ

Can React Context replace Redux?

For small apps and rarely changing shared values, yes. For complex, frequently updated state used across many components, Context lacks selectors, middleware, and DevTools, so Redux Toolkit or a lighter store is usually a better fit.

Is Redux still relevant?

Yes. Redux Toolkit is a well-maintained, widely used choice for large applications, especially with RTK Query. Many smaller apps no longer need it once server state is handled by a dedicated library.

Why does my whole app re-render when context changes?

Every component that reads a context re-renders when the provider's value changes, and a value object created on each render counts as a change. Split contexts, memoize values, or move fast-changing state to a store with selectors.

Should I use Zustand instead of Redux?

Zustand offers selector-based subscriptions with very little setup and suits many apps well. Redux Toolkit offers stronger conventions, middleware, DevTools, and RTK Query, which help larger teams and complex state.

Where should API data live?

In a server-state library such as TanStack Query or RTK Query, which handles caching, refetching, loading states, and invalidation. Avoid copying API responses into Context or general-purpose stores.

Related Topics

References