Skip to content

Zustand

A small, hook-based store with almost no ceremony.

Web & HTTPState ManagementJavaScript

What it is

Zustand is a small, fast, and scalable state management library for React. It provides a simple API to create global state stores with minimal boilerplate, using hooks for accessing and updating state.

Zustand allows you to create a store that holds your global state. Components can read from and write to the store using hooks. It supports derived state, middleware, and persistence without forcing a specific architecture.

Licence
MIT
Best known for
A working store in about five lines

When to use it

The question documentation cannot answer for you — because it cannot recommend something else.

Reach for it when

  • You need shared client state and Redux feels disproportionate
  • You want a store you can read outside React components as easily as inside

Look elsewhere when

  • The state is really cached server data — use React Query or SWR
  • Your team specifically wants Redux's enforced structure and action log

Installation

npm install zustand

Getting started

The smallest useful thing you can do with it, and what each part means.

Creating a simple store
import create from 'zustand';

const useStore = create(set => ({
  count: 0,
  increment: () => set(state => ({ count: state.count + 1 })),
  decrement: () => set(state => ({ count: state.count - 1 }))
}));
Defines a store with a `count` state and functions to increment and decrement it.
Using the store in a component
function Counter() {
  const { count, increment, decrement } = useStore();
  return (
    <div>
      <button onClick={decrement}>-</button>
      <span>{count}</span>
      <button onClick={increment}>+</button>
    </div>
  );
}
Accesses state and actions from the store inside a React component.

Advanced usage

Where the library earns its place over a simpler alternative.

Derived state
const useStore = create(set => ({
  count: 0,
  double: () => set(state => ({ count: state.count * 2 }))
}));

const doubledCount = useStore(state => state.count * 2);
Demonstrates creating derived values from the store’s state.
Middleware example
import { persist } from 'zustand/middleware';
const useStore = create(persist(
  set => ({ count: 0, increment: () => set(state => ({ count: state.count + 1 })) }),
  { name: 'counter-storage' }
));
Adds persistence to the store so state is saved in localStorage.
Combining multiple actions
const useStore = create(set => ({
  count: 0,
  incrementBy: (n) => set(state => ({ count: state.count + n })),
  reset: () => set({ count: 0 })
}));
Shows multiple actions including parameterized state updates and resetting state.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

State not updating in component
Ensure you are using the hook returned by the store and not a stale reference. Destructure state inside the component.
Performance issues with large state
Split state into multiple smaller stores and select only needed slices with hooks.
Persisted state not working
Check that the `persist` middleware is correctly applied and browser localStorage is accessible.

Best practices

  • Use small, focused stores for different concerns rather than one large global store.
  • Leverage hooks to read only the parts of state needed by a component to avoid unnecessary re-renders.
  • Use middleware like `persist` or `redux-devtools-extension` for debugging and persistence.
  • Keep state updates immutable even though Zustand allows direct mutation in set functions.
  • Encapsulate complex logic inside actions rather than inside components.

Alternatives

Comparable options, and the reason you would pick one over the other.

Background

Why it exists, and what it was reacting to.

Zustand was created by Jotai and React community contributors to offer an alternative to heavier state management libraries like Redux. It emphasizes simplicity, ease of use, and minimalistic design while being highly performant and flexible for both small and large applications.