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.