Why I ditched Redux Toolkit, MobX, and Context API for Zustand
Why I ditched Redux Toolkit, MobX, and Context API for Zustand
My hands were cramping from writing Redux Toolkit code. Same pattern, same code, just different names. createAsyncThunk — write. Slice — write. ExtraReducer — write. Loading, success, error — write again. Three API calls — repeat three times. Ten calls — ten times. It's tedious, error-prone, and most importantly — unnecessary.
MobX was a different story. Decorators, observables, reactions. Lots of "magic". It works, but understanding what's happening underneath is hard. When a bug surfaces, tracking it down takes hours. In a large team, MobX becomes a "trust me bro" pattern. Nobody has full control.
Context API is a whole different beast. React ships it, says "go ahead, use it." But when you do — re-renders everywhere, optimization nightmares. No selectors, no DevTools, debugging is a mess. Ten components tied to one context — one changes, all re-render. Fine for a small project. For a large one? Headache.
When I first saw Zustand, I thought "that's it?" One function, one store. That's all.
const useStore = create((set) => ({
user: null,
loading: false,
fetchUser: async (id) => {
set({ loading: true })
const user = await api.getUser(id)
set({ user, loading: false })
},
}))No slices, no thunks, no extraReducers, no providers, no decorators. Just a function. It works. Done.
Selective re-rendering? Built-in. Pass a selector — only that value triggers a re-render. Nothing else.
const count = useStore((state) => state.count)Redux DevTools integration? Yes. Immer support? Yes. None of it is mandatory.
1 KB. That's it.