Zustand: Tiny State Management That Won't Eat Your Zombie Children
State management in React can feel like choosing between a sledgehammer and a scalpel. Redux gives you structure but weight. Context gives you simplicity but scaling headaches. And then there's Zustand—a tiny, fast state manager that does one thing remarkably well: it doesn't break when your components go through lifecycle quirks.
If you've ever dealt with the dreaded "setState on unmounted component" warning or watched a stale closure ruin your day, Zustand handles that elegantly. It's built by the same folks behind React Three Fiber, so it's battle-tested in complex rendering scenarios.
What It Does
Zustand is a minimal state management library for React. You create a store with a function, get state and actions back, and use them in components. That's it. No providers, no reducers, no boilerplate. The whole library is about 1 KB (minified + gzipped). You write plain functions, and Zustand handles subscriptions, memoization, and garbage collection.
The core API looks like this:
import { create } from 'zustand'
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
function Counter() {
const count = useStore((state) => state.count)
const increment = useStore((state) => state.increment)
return <button onClick={increment}>{count}</button>
}
No wrapping your app in <Provider>. No connect(). Just a hook that returns exactly what you need.
Why It's Cool
The headline feature—getting zombie children right—sounds esoteric but matters deeply. "Zombie children" happen when a child component tries to read state from a parent that's already been unmounted. Most state managers crash or throw warnings here. Zustand avoids that by separating state subscriptions from component lifecycles. If a component dies, Zustand quietly cleans up its subscription without throwing errors.
Other neat things:
- Batched updates by default – No manual batching needed. Zustand uses React 18's automatic batching when available.
- No boilerplate – One function call per store. No action types, no dispatch, no reducers.
- Middleware support – You can plug in
persist,immer,devtools, or write your own. - Works outside React – The store is just a JavaScript object. You can read/write to it in vanilla JS, which makes it great for non-React contexts or testing.
- Subscriptions are smart – You can subscribe to specific slices of state and only re-render when those change. Simple object equality by default, or pass a custom comparator.
How to Try It
Install it:
npm install zustand
Or grab a starter from their examples repo. The official docs are refreshingly short and direct. If you want a quick sandbox, check out their CodeSandbox examples linked in the GitHub repo.
For a real quick test, copy the counter example above into any React project. Watch how it works without any setup. Then try adding a nested component that mounts late and reads state from the store—it just works.
Final Thoughts
Zustand isn't trying to be the next Redux or a full framework. It's a focused tool for a common problem: you need state that multiple components can share, without ceremony. If you're building a small to medium app, or even a complex one where you want to avoid reducer fatigue, Zustand is a breath of fresh air.
It's not hype—it's just a tiny library that does one thing well and gets out of your way. And that zombie children thing? You'll only appreciate it when you debug a heisenbug caused by stale subscriptions. Trust me, it's worth the 1 KB.
Follow us on @githubprojects for more developer tools and projects.
Repository: https://github.com/pmndrs/zustand