All posts

Why I Switched from Redux to Zustand (And Never Looked Back)

·Alex Chen
ReactState ManagementTypeScript

I've been writing React applications since 2018, and for most of that time, Redux was my default choice for global state management. It's predictable, well-documented, and the ecosystem is enormous. But somewhere around my fifth time writing an createSlice, useSelector, and corresponding thunk for a simple piece of UI state, I started questioning whether I was adding complexity without enough value in return.

The breaking point

The project that pushed me over the edge was a medium-sized dashboard application. We had a Redux store with 14 slices, each with their own selectors, reducers, and async actions. The state itself was maybe 3KB of data, but the code managing it was several hundred lines of boilerplate spread across a store directory.

When a new engineer joined the team, it took them a full week to understand where state lived and how to modify it safely. That's when I realized the "separation of concerns" argument for Redux wasn't paying off.

Enter Zustand

Zustand describes itself as "a small, fast, and scalable bearbones state management solution." That description undersells how refreshing it is to use.

Here's the same piece of state in both Redux and Zustand:

Redux:

// authSlice.ts
const authSlice = createSlice({
  name: 'auth',
  initialState: { user: null, isLoading: false },
  reducers: {
    setUser: (state, action) => { state.user = action.payload },
    setLoading: (state, action) => { state.isLoading = action.payload },
  },
})
export const { setUser, setLoading } = authSlice.actions
export const selectUser = (state: RootState) => state.auth.user

Zustand:

// useAuthStore.ts
const useAuthStore = create<AuthStore>((set) => ({
  user: null,
  isLoading: false,
  setUser: (user) => set({ user }),
  setLoading: (isLoading) => set({ isLoading }),
}))

The Zustand version is a third of the lines, lives in one file, and is completely TypeScript-friendly without any extra setup.

What I gave up

Switching isn't free. A few things I missed from Redux:

  • Redux DevTools integration — Zustand has a devtools middleware, but it's not as polished
  • Time-travel debugging — genuinely useful when tracking down subtle state bugs
  • Middleware ecosystem — Redux's middleware story is mature; Zustand is catching up

For my use case, these tradeoffs were worth it. But for larger teams working on complex applications where auditability matters, Redux may still be the right call.

The verdict

Zustand is my default now for new projects. It gets out of your way, plays nicely with TypeScript, and doesn't require you to learn a new mental model. If you're starting a greenfield React app and don't already have strong opinions on state management, give it a try.