Goodbye Redux Boilerplate? A Detailed Guide to the Lightweight Zustand State Manager
1. The “Trouble” with Redux
Redux is unquestionably the best-known and most powerful state-management library in the React ecosystem. Features such as unidirectional data flow and time-travel debugging make it a reliable choice for large, complex applications. For many small and medium-sized projects, however, Redux’s “boilerplate” is often a headache:
- Actions & Action Creators: Defining many action types and creator functions.
- Reducers: Writing large
switchstatements to handle different actions. - Dispatch & Selectors: Dispatching actions with
dispatchand subscribing to state changes withuseSelectorinside components. - Context Provider: Wrapping the application root in a
<Provider>.
All of this means that adding even a simple piece of state requires changes across several files, making the process cumbersome.
2. Zustand: A Breath of Fresh Air
Zustand (German for “state”) is a lightweight state-management library developed by the Poimandres team, the creators of react-three-fiber. Its design philosophy is minimalism and non-intrusiveness.
Core features:
- Very little code: Implementing a feature with Zustand usually requires only a fraction of the code needed with Redux.
- Hooks-based: Everything revolves around a custom Hook, fitting naturally into modern React development.
- No Context Provider required: You do not need to wrap the top level of the application in any Provider. The store is independent of the component tree and can be imported and used anywhere.
- Easy to learn: The API is extremely simple, and its core usage can be learned in minutes.
3. Core Usage
Using Zustand involves two steps: creating a Store and using it in a component.
a. Creating a Store
You can define a store in any .js or .ts file.
// src/store.js
import { create } from 'zustand';
const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}));
export default useBearStore;The create function receives a callback whose argument is the set function, similar to React’s setState. This is where you define your state and the methods that update it.
b. Using It in a Component
Use it in any component just like an ordinary Hook.
// src/components/BearCounter.jsx
import useBearStore from '../store';
function BearCounter() {
const bears = useBearStore((state) => state.bears);
return <h1>{bears} around here ...</h1>;
}Notice that we subscribe through the selector function (state) => state.bears to the bears state. This is important because it ensures that the component rerenders only when bears changes, avoiding unnecessary performance costs.
// src/components/Controls.jsx
import useBearStore from '../store';
function Controls() {
const increasePopulation = useBearStore((state) => state.increasePopulation);
return <button onClick={increasePopulation}>one up</button>;
}Getting an action is just as simple.
4. Asynchronous Actions
Zustand also handles asynchronous operations naturally. You do not need middleware such as redux-thunk or redux-saga.
const useAsyncStore = create((set) => ({
data: null,
fetchData: async (url) => {
const response = await fetch(url);
const data = await response.json();
set({ data });
},
}));Conclusion
Zustand is not intended to replace Redux completely. Redux still has advantages in strict conventions, traceability, and its vast ecosystem.
For the overwhelming majority of React applications, however, Zustand offers a simpler and faster choice with less mental overhead. If you are tired of Redux’s formalities, or your next project needs a nimble and flexible state manager, Zustand is certainly an excellent option worth trying.