State Management with Zustand
Creating a Zustand Store
Zustand's create() function defines a store in one step: you provide a function that receives set (for updating state) and returns the initial state plus any update functions, all in one plain object — no separate actions, reducers, or types required.
Note: Unlike Redux, there's no Provider needed — the store created by create() is just a React hook you can import and call anywhere.
Warning: Define the store once at module scope (outside any component) — creating it inside a component would reset it on every render.
Example: Creating a Zustand Store
// Run in your local React project (npm install required)
import { create } from 'zustand';
const useCounterStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
}));
⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.
Using the Store in a Component
A Zustand store is used just like any other custom hook. Calling useCounterStore(state => state.count) subscribes the component to just that field, re-rendering only when it changes — similar in spirit to Redux's useSelector, but built directly into the store hook itself.
Note: Select only the specific fields/functions you need, rather than the whole store object, to avoid unnecessary re-renders.
Warning: Calling useCounterStore() with no selector returns the ENTIRE store state, re-rendering the component on any change to any field.
Example: Using the Store in a Component
// Run in your local React project (npm install required)
function Counter() {
const count = useCounterStore(state => state.count);
const increment = useCounterStore(state => state.increment);
return <button onClick={increment}>Count: {count}</button>;
}
Zustand vs. Redux
Zustand trades some of Redux's strict structure (separate actions/reducers/types) for a much smaller, more direct API, making it faster to get started with for small-to-medium apps. Redux's stricter conventions can pay off more in very large teams/codebases where that structure aids consistency.
Note: If a team is used to Redux's patterns and DevTools workflow, that familiarity is worth weighing against Zustand's smaller learning curve.
Warning: Zustand's flexibility means there's less enforced structure — larger Zustand codebases benefit from establishing their own conventions for organizing stores.
Example: Zustand vs. Redux
// Run in your local React project (npm install required)
// Redux: separate action, reducer, dispatch, Provider, useSelector/useDispatch
// Zustand: one create() call, no Provider, direct hook usage:
const useStore = create(set => ({
user: null,
login: name => set({ user: name }),
}));
function Profile() {
const user = useStore(s => s.user);
return <p>{user || "Not logged in"}</p>;
}
- Selecting the entire store object in a component instead of just the specific field needed, causing extra re-renders.
- Mutating state directly outside of the store's set function.
- Creating a new store instance inside a component instead of defining it once at module scope.
- Zustand is a minimal state-management library with far less boilerplate than Redux.
- A store is created with the create() function, defining state and update functions together.
- Components read from the store by calling the store hook with a selector function.
- No Provider component is required — the store is just a hook you import and use directly.
Requires npm install zustand — not available via CDN in this sandbox.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: