Overview
Use Zustand for new React work. It is 1 KB, uses one hook, and gets out of the way. Use Redux Toolkit (RTK) only when the team already runs a large Redux codebase, needs Redux DevTools’ time-travel debugging across many engineers, or wants RTK Query bundled with the state library. The 2026 default for client state is Zustand; Redux is the niche pick now. See react-state-management for the upstream rule set.
When Zustand wins
Zustand is the right pick for nearly every new React app that needs client state beyond useState.
- API surface:
create((set) => ({ count: 0, inc: () => set((s) => ({ count: s.count + 1 })) }))is the whole library. New contributors are productive in 20 minutes. - No provider: stores are plain modules. No
<Provider>wrappingApp, no boilerplate context, no nested store provider trees. - Bundle: 1 KB gzipped. Redux Toolkit is 12 to 15 KB plus React-Redux bindings. On a content app with one store, the gap matters.
- Selectors with referential stability:
useStore((s) => s.user)re-renders only whenuserchanges. Noreselect, no memoization plumbing. - Server-state stays out: Zustand does not pretend to fetch data. Pair it with TanStack Query or SWR; see tanstack-query-vs-swr.
- Middleware when needed:
persist,devtools,immer,subscribeWithSelector. Each is opt-in. - Works with React Server Components: stores are client-side; you instantiate per-request via a provider only when the app needs SSR with per-user state.
When Redux wins
Redux Toolkit is the right pick in three concrete cases. Outside them, the choice is Zustand.
- Existing Redux codebase past 50k LoC with a team that knows the patterns. Rewriting to Zustand is rarely the highest-value engineering work.
- Time-travel debugging is a real workflow on the team: Redux DevTools’ action log, replay, and import/export of state are unmatched. Useful on complex apps with a QA team or designers reproducing bugs.
- RTK Query is the data layer. RTK Query couples server-state caching to the Redux store with code generation from OpenAPI. If the team committed to it, swapping to TanStack Query plus Zustand is a meaningful migration.
- Large-team discipline: 30-plus engineers benefit from the enforced action and reducer shape. Zustand’s freedom is a footgun at that scale unless the team writes its own conventions.
- Strict event sourcing or audit trail requirements where every state change is a named action. Zustand can do this but does not enforce it.
Trade-offs at a glance
| Dimension | Zustand | Redux Toolkit |
|---|---|---|
| Bundle (gzipped) | 1 KB | 12 to 15 KB plus React-Redux |
| API | One hook, plain modules | Slices, reducers, actions, thunks |
| Provider needed | Only for SSR per-request stores | Always (<Provider store={store}>) |
| Boilerplate | Minimal | Slim with RTK; still more than Zustand |
| Selectors | Built-in equality, no memoization needed | createSelector for derived state |
| Async | Plain functions in actions | createAsyncThunk or RTK Query |
| Data fetching | External (TanStack Query, SWR) | RTK Query bundled |
| DevTools | Browser extension via middleware | First-class time-travel and replay |
| Hiring familiarity | Growing; default in new React work | High; legacy in many enterprises |
| Cross-framework | React focus; React Native works | React-Redux, Vue-Redux, others |
| TypeScript | Excellent inference | Good; more explicit types |
| Sweet spot | New apps; small to medium teams | Large legacy fleets; RTK Query users |
Migration cost
Redux-to-Zustand is the common direction and usually pays back inside a quarter. The reverse is rare.
- Redux to Zustand: port slice by slice. Each Redux slice becomes a Zustand store; selectors map one-to-one. Replace dispatched actions with store methods. Plan one engineer-week per 10 slices. The hard part is component updates, which a codemod covers for roughly 60 percent.
- Redux Thunk or Saga to Zustand: rewrite async logic as plain functions in the store. Saga’s effect helpers do not map cleanly; budget extra time if the app uses them heavily.
- RTK Query to TanStack Query: orthogonal swap, well-trodden. Plan one engineer-day per 20 endpoints.
- Cheaper path: keep Redux for the legacy area, build new features in Zustand. Two stores coexist; React does not care.
Recommendation
- New React app: Zustand. No exceptions worth listing for greenfield work.
- Pair with TanStack Query for server state; see tanstack-query-vs-swr.
- Existing Redux Toolkit app, no friction: stay. Rewriting state libraries rarely beats shipping features.
- Existing classic Redux app (pre-RTK): migrate to Zustand on the next feature touching that area; do not big-bang rewrite.
- App that genuinely uses Redux DevTools’ time-travel daily: Redux Toolkit.
- Library author shipping reusable hooks: Zustand. Smaller surface area imposes less on consumers.
- See react-state-management for the upstream “where does state live” decision.