Skip to content

Guide · Open source

How to use zustand: install, create a store and bind React components

Updated · written with AI from the project's own documentation and checked against our catalogue data

Zustand is a small state-management library for React that keeps shared state in a store you read through a hook. This guide shows you how to install it, create a store, connect components to it and use a few common patterns from the README. By the end you will be able to share state between components without context providers.

Zustandpmndrs/zustand · ★ 58.9k · MIT

Quick start

  1. 1Install the package. Run npm install zustand in your project. You need Node.js and npm installed.
  2. 2Create the store. Call create with a function that receives set and returns your initial state and actions.
  3. 3Select state in components. Call your store hook inside a component and pass a selector that picks only the value you need.
  4. 4Update state with actions. Call set inside an action to merge new values into the store; use get when an action needs current state.
  5. 5Pick multiple values safely. Wrap object or array selectors in useShallow from zustand/react/shallow to avoid unnecessary re-renders.
  6. 6Access state outside components. Use getState, setState and subscribe on the hook when code outside React needs to read or change the store.

Install zustand with npm

Zustand is installed as a package. You need Node.js and npm available on your machine, then run the install command from the project directory.

  • Prerequisites: Node.js and npm
  • Install with the package manager, not a download
npm install zustand

Create a store

Your store is a hook. You can put primitives, objects or functions in it. The create function receives a set function, and set merges new values into the state, so you only write the keys that change. The README notes that state should be updated immutably.

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

Read state in components with selectors

Call the hook anywhere, no provider is needed. Pass a selector function that picks the piece of state the component needs. The component re-renders only when that selected value changes, so a button that only needs an action does not re-render when the count changes.

  • Select one value per call for the default strict-equality check
  • Use the hook without a selector only if you want the whole state, which re-renders on every change
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> }

Select several values without extra re-renders

If you pick several values into one object or array, a new object is created on every call and can cause unneeded re-renders. The README recommends useShallow from zustand/react/shallow, which compares the selector output shallowly.

For custom comparison logic, the README points to createWithEqualityFn, which takes an equality function as a second argument.

  • Import useShallow from 'zustand/react/shallow'
  • Use it to pick objects, arrays or mapped keys
import { useShallow } from 'zustand/react/shallow' const { nuts, honey } = useBearStore( useShallow((state) => ({ nuts: state.nuts, honey: state.honey })), )

Read and update state outside components

Sometimes code outside React needs the current state or needs to change it. The hook has utility functions attached, including getState, setState and subscribe. Inside actions, get lets you read current state.

The README warns against using this technique to add state in React Server Components, because it can cause unexpected bugs and privacy issues for users.

  • getState returns fresh state without subscribing
  • setState triggers listeners and components that select changed values
  • subscribe returns an unsubscribe function you call when done
  • subscribeWithSelector from zustand/middleware lets you subscribe to a selected slice
const useDogStore = create(() => ({ paw: true, snout: true, fur: true })) const paw = useDogStore.getState().paw const unsub1 = useDogStore.subscribe(console.log) useDogStore.setState({ paw: false }) unsub1()

Use zustand without React

The core can be imported without React. The create function from zustand/vanilla returns the store API utilities instead of a hook. The README describes this as a secondary option; the main focus is JavaScript and React usage. The README also says a vanilla store can be used with the useStore hook.

  • Import createStore from 'zustand/vanilla'
  • Destructure getState, setState, subscribe and getInitialState from the store
import { createStore } from 'zustand/vanilla' const store = createStore((set) => ...) const { getState, setState, subscribe, getInitialState } = store export default store

What people use it for

  • Sharing a counter or cart total across many components without wrapping the app in providers
  • Storing fetched data in an async action that calls set when the response arrives
  • Keeping UI state that components select in small pieces so only affected components re-render
  • Reacting to store changes in plain JavaScript code with subscribe, using the vanilla core

Frequently asked questions

How do I install zustand?

Run npm install zustand in your project. The README lists Node.js and npm as the prerequisites.

Do I need a context provider to use zustand?

No. The README says you can use the store hook anywhere and no providers are needed. Components that select state re-render only when the selected values change.

Is zustand free to use?

The repository is licensed under MIT. Check the LICENSE file in the repository for the full terms.

Can I use zustand without React?

Yes, the core can be imported from zustand/vanilla. The README says this is a secondary option, and the library's main focus is JavaScript and React usage.

Why does my component re-render too often with zustand?

If your selector returns a new object or array, the comparison may fail on each call. The README suggests wrapping the selector in useShallow, or selecting individual values instead.

How does zustand compare to Redux?

The README describes zustand as simple and un-opinionated, with hooks as the main way to consume state and no context providers. Redux has more conventions, tooling and strict structure, which some teams prefer.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

Zustand suits React developers who want shared state with little setup, fine control over re-renders and optional access outside components. Teams that want Redux's conventions and strict structure, or projects that are not based on React or JavaScript, should look at other options such as Redux or Jotai.

Install options & downloads