Zustand

Last edited by dave on 01/12/2025, 07:13:46 UTC

Zustand

Contents

Zustand Logo

Quick Snapshot

  • Type: Small, fast, and unopinionated state management library for React.
  • Created by: Jotai and React-spring author Poimandres (led by Daishi Kato).
  • First released: 2019.
  • Core idea: Manage global or local state with minimal boilerplate and zero magic.
  • Name meaning: “Zustand” is German for state — fittingly simple.
  • GitHub repo: pmndrs/zustand

Why Zustand Exists

React gives you useState and useContext, which are great — until your app grows, your props start drilling, and your mental stack collapses.
Other state libraries like Redux can feel heavy, verbose, or too “enterprisey.”

Zustand sits in the sweet spot:

  • Simpler than Redux
  • More scalable than Context
  • Smaller than you’d expect (around 1KB gzipped)

It’s the “just enough” solution for managing state without making your codebase cry.


Core Concepts

The Store

At its core, Zustand revolves around a store — a single source of truth for your data.
You create it with create(), and consume it anywhere using a hook.

import { create } from 'zustand' const useBearStore = create((set) => ({ bears: 0, increase: () => set((state) => ({ bears: state.bears + 1 })), }))

Then in your React component:

function BearCounter() { const { bears, increase } = useBearStore() return ( <h1 onClick={increase}> 🐻 Count: {bears} </h1> ) }

That’s it. No reducers, no actions, no dispatch — just state.


How It Works

  • Zustand uses hooks for access — no Provider needed.
  • State updates trigger re-renders only in components that use that slice of state.
  • You can split stores or combine them freely.
  • Under the hood, Zustand uses subscribe functions and selectors for granular control.

Selectors & Performance

To avoid unnecessary re-renders, you can use selectors:

const bears = useBearStore((state) => state.bears)

This way, only components relying on bears will re-render when it changes — not everything else.

For even more control:

const bears = useBearStore((state) => state.bears, shallow)

Here, shallow comparison (from Zustand) helps prevent re-renders when the selected state hasn’t truly changed.


Middleware Goodies

Zustand supports middleware to supercharge your store:

  • persist — Save state to localStorage or sessionStorage.
  • devtools — Integrate with Redux DevTools for debugging.
  • immer — Mutate state safely using Immer syntax.
  • subscribeWithSelector — Subscribe to specific slices of the store.

Example with persistence:

import { create } from 'zustand' import { persist } from 'zustand/middleware' const useUserStore = create(persist( (set) => ({ name: '', setName: (name) => set({ name }), }), { name: 'user-storage' } ))

Now your user’s name survives page reloads like a champ.


Async Actions

Need to fetch data? No problem:

const useStore = create((set) => ({ data: null, fetchData: async () => { const res = await fetch('/api/data') const data = await res.json() set({ data }) } }))

Zustand doesn’t care what’s inside your functions — sync or async, it just runs.


TypeScript Support

Zustand plays beautifully with TypeScript:

interface BearState { bears: number increase: () => void } const useBearStore = create<BearState>()((set) => ({ bears: 0, increase: () => set((state) => ({ bears: state.bears + 1 })), }))

Type inference works automatically for state and actions — no gymnastics required.


When to Use Zustand

Zustand fits perfectly when:

  • You’ve outgrown simple useState / useContext.
  • Redux or Recoil feels like overkill.
  • You want a minimal, flexible, and performant global store.
  • You’re building React apps, Next.js projects, or React Native apps.

Zustand also works great alongside other tools — it doesn’t try to own your architecture.


Common Patterns

Split stores:
You can create multiple smaller stores for modularity.

const useThemeStore = create((set) => ({ dark: false, toggle: () => set((s) => ({ dark: !s.dark })) }))

Derived state:
Compute values directly in selectors.

const total = useCartStore((s) => s.items.reduce((a, i) => a + i.price, 0))

Combined stores:
Compose stores for more complex logic (e.g. auth + preferences).


Ecosystem & Integrations

  • Works with React, React Native, and Next.js out of the box.
  • Pairs well with Immer, React Query, and Jotai.
  • Plays nicely with devtools and server components.
  • Fully compatible with concurrent React (React 18+).

Fun Facts

  • The name “Zustand” literally means state in German.
  • You can use multiple stores in one app without context providers.
  • Its logo? A friendly little bear — because every example starts with one.
Backlinks (3)
Categories (0)

    No categories assigned to this page.

Edit Level

> Signed In Users