For years, “React + Redux” was the default answer. But in 2025, maintaining a massive Redux store for a medium-sized application felt like driving a semi-truck to the grocery store.
The Boilerplate Fatigue
To add a single feature, we had to touch four files: actions.ts, types.ts, reducer.ts, and the component itself. It made onboarding new juniors a nightmare.
The Alternative: Zustand
We proof-of-concepted Zustand for a new feature. The code was shockingly simple:
const useStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
}))
No providers, no context wrapping, just a hook. It felt like cheating.
The Migration
We didn’t rewrite everything at once. We started moving isolated modules (like the User Profile and Settings) to Zustand. For global server state (like loading lists of items), we actually replaced Redux with TanStack Query.
That was the real game changer. Most of our “Global State” was just server cache. TanStack Query handled loading, error, and stale states automatically.
Verdict
Our codebase is now 30% smaller. State logic is co-located with the features that need it. If you are starting a new project in 2025, think twice before running npm install redux.