Zustand State Management
Zustand is a lightweight, fast, and scalable state-management solution for React, built on simplified flux principles. It offers a comfortable API based on hooks, designed to be unopinionated and address common React pitfalls like the zombie child problem. The current stable version is 5.0.12, with active development and frequent patch releases.
Common errors
-
TypeError: Cannot destructure property 'create' of 'zustand' as it is undefined.
cause Attempting to use CommonJS `require` syntax for `zustand` which might primarily target ESM, or an incorrect module import path.fixEnsure you are using `import { create } from 'zustand'` and your build system is configured for ESM. -
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
cause Calling `useBearStore` or any other Zustand store hook outside of a React function component or another custom React Hook.fixEnsure all Zustand store hooks are invoked exclusively within the top level of React function components or custom hooks. -
TypeError: Cannot read properties of undefined (reading 'propertyName')
cause A `set` callback returned `void` or `undefined` instead of a state object, causing the store state to become invalid or partial updates to fail.fixAlways ensure `set` callbacks return a complete (or new partial) state object. For example, `set((state) => ({ ...state, propertyName: newValue }))`.
Warnings
- gotcha State updates must be immutable. Directly modifying state objects will not trigger re-renders or correctly persist changes.
- gotcha Selecting the entire store state (e.g., `useBearStore()`) will cause your component to re-render on *any* state change within the store, which can lead to performance issues.
- gotcha Selectors use strict-equality (`old === new`) for comparison by default. If your selector returns a new object or array on every render, it will cause unnecessary re-renders even if the underlying data is shallowly identical.
- gotcha When using the `persist` middleware, directly manipulating the underlying storage (like `localStorage`) outside of Zustand's API can lead to state inconsistencies or race conditions, especially during concurrent rehydration.
Install
-
npm install zustand -
yarn add zustand -
pnpm add zustand
Imports
- create
const { create } = require('zustand')import { create } from 'zustand'
Quickstart
import { create } from 'zustand';
const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}));
function BearCounter() {
const bears = useBearStore((state) => state.bears);
return <h1>{bears} around here ...</h1>;
}
function Controls() {
const increasePopulation = useBearStore((state) => state.increasePopulation);
return <button onClick={increasePopulation}>one up</button>;
}