A small, fast and scalable state management solution for React applications using simplified flux principles
npx @tessl/cli install tessl/npm-zustand@5.0.0Zustand is a small, fast and scalable bearbones state-management solution using simplified flux principles. It has a comfy API based on hooks that isn't boilerplatey or opinionated, and eliminates common React state management pitfalls including zombie child problems, React concurrency issues, and context loss between mixed renderers.
npm install zustandimport { create } from "zustand";For CommonJS:
const { create } = require("zustand");For vanilla (non-React) usage:
import { createStore } from "zustand/vanilla";For middleware:
import { devtools, persist, subscribeWithSelector } from "zustand/middleware";
import { redux, combine } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";For utilities:
import { shallow } from "zustand/shallow";
import { useShallow } from "zustand/react/shallow";For traditional API with equality functions:
import { createWithEqualityFn, useStoreWithEqualityFn } from "zustand/traditional";import { create } from "zustand";
// Define your store
interface BearState {
bears: number;
increase: (by: number) => void;
}
const useBearStore = create<BearState>((set) => ({
bears: 0,
increase: (by) => set((state) => ({ bears: state.bears + by })),
}));
// Use in React components
function BearCounter() {
const bears = useBearStore((state) => state.bears);
return <h1>{bears} around here ...</h1>;
}
function Controls() {
const increasePopulation = useBearStore((state) => state.increase);
return <button onClick={() => increasePopulation(1)}>one up</button>;
}Zustand is built around several key components:
useSyncExternalStoreCore functionality for creating and managing state stores, available in both React and vanilla JavaScript environments.
function create<T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
): UseBoundStore<Mutate<StoreApi<T>, Mos>>;
function createStore<T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
): Mutate<StoreApi<T>, Mos>;
type StateCreator<T, Mis extends [StoreMutatorIdentifier, unknown][] = [], Mos extends [StoreMutatorIdentifier, unknown][] = [], U = T> = ((
setState: Get<Mutate<StoreApi<T>, Mis>, 'setState', never>,
getState: Get<Mutate<StoreApi<T>, Mis>, 'getState', never>,
store: Mutate<StoreApi<T>, Mis>
) => U) & { $$storeMutators?: Mos };React hooks and components for consuming Zustand stores with automatic re-rendering and selector support.
function useStore<S extends ReadonlyStoreApi<unknown>>(api: S): ExtractState<S>;
function useStore<S extends ReadonlyStoreApi<unknown>, U>(
api: S,
selector: (state: ExtractState<S>) => U
): U;
type UseBoundStore<S extends ReadonlyStoreApi<unknown>> = {
(): ExtractState<S>;
<U>(selector: (state: ExtractState<S>) => U): U;
} & S;Extensible middleware system for adding DevTools integration, persistence, Redux-style actions, and custom behaviors.
function devtools<T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = [], U = T>(
initializer: StateCreator<T, [...Mps, ['zustand/devtools', never]], Mcs, U>,
devtoolsOptions?: DevtoolsOptions
): StateCreator<T, Mps, [['zustand/devtools', never], ...Mcs]>;
function persist<T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = [], U = T>(
initializer: StateCreator<T, [...Mps, ['zustand/persist', unknown]], Mcs>,
options: PersistOptions<T, U>
): StateCreator<T, Mps, [['zustand/persist', U], ...Mcs]>;
function subscribeWithSelector<T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [...Mps, ['zustand/subscribeWithSelector', never]], Mcs>
): StateCreator<T, Mps, [['zustand/subscribeWithSelector', never], ...Mcs]>;Helper functions for shallow comparison, state combination, and traditional APIs with equality functions.
function shallow<T>(valueA: T, valueB: T): boolean;
function useShallow<S, U>(selector: (state: S) => U): (state: S) => U;
function combine<T extends object, U extends object, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(
initialState: T,
create: StateCreator<T, Mps, Mcs, U>
): StateCreator<Write<T, U>, Mps, Mcs>;Alternative API for projects that need custom equality functions, providing compatibility with older patterns.
function createWithEqualityFn<T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>,
defaultEqualityFn?: <U>(a: U, b: U) => boolean
): UseBoundStoreWithEqualityFn<Mutate<StoreApi<T>, Mos>>;
function useStoreWithEqualityFn<S extends ReadonlyStoreApi<unknown>>(
api: S
): ExtractState<S>;
function useStoreWithEqualityFn<S extends ReadonlyStoreApi<unknown>, U>(
api: S,
selector: (state: ExtractState<S>) => U,
equalityFn?: (a: U, b: U) => boolean
): U;interface StoreApi<T> {
setState: SetStateInternal<T>;
getState: () => T;
getInitialState: () => T;
subscribe: (listener: (state: T, prevState: T) => void) => () => void;
}
type ExtractState<S> = S extends { getState: () => infer T } ? T : never;
interface StoreMutators<S, A> {}
type StoreMutatorIdentifier = keyof StoreMutators<unknown, unknown>;
type Mutate<S, Ms> = number extends Ms['length' & keyof Ms]
? S
: Ms extends []
? S
: Ms extends [[infer Mi, infer Ma], ...infer Mrs]
? Mutate<StoreMutators<S, Ma>[Mi & StoreMutatorIdentifier], Mrs>
: never;
type UseBoundStoreWithEqualityFn<S extends ReadonlyStoreApi<unknown>> = {
(): ExtractState<S>;
<U>(
selector: (state: ExtractState<S>) => U,
equalityFn?: (a: U, b: U) => boolean
): U;
} & S;
type ReadonlyStoreApi<T> = Pick<StoreApi<T>, 'getState' | 'getInitialState' | 'subscribe'>;
type Write<T, U> = Omit<T, keyof U> & U;