With server state in TanStack Query 79,069 , the client store only holds what the server doesn't know about. The three common choices for it compare like this:
| React 7,897 context | Zustand 5 | Redux Toolkit 2 | |
|---|---|---|---|
| Setup | A provider per context | One create() call, no provider | Store, slices, provider |
| Re-renders | Every consumer, on any change | Only when the selected value changes | Only when the selected value changes |
| Tooling | React DevTools 7,897 | Optional devtools middleware | Redux DevTools 14,368 , time travel |
| Persistence | Write it yourself | persist middleware | redux-persist 12,951 or listeners |
Context is fine for values that rarely change, such as the signed-in user BookNest keeps in src/session.tsx; splitting a context per concern, or memoizing its value, limits the damage when it does change. Zustand suits small and medium apps: the whole cart store in Zustand is about 30 lines, and a component subscribes to exactly what it reads. Redux Toolkit earns its structure in large teams, where a traceable path for every change and time-travel debugging matter more than brevity. Jotai 21,282 (atoms) and MobX 3,824 (observables) are other open-source options. Whichever you pick, keep server data out of it.