pmndrs /zustand

🐻 Bear necessities for state management in React

★ 58,909⑂ 2,191👁 190⑃ 1,240● 699▤ 107◈ 1,528
TypeScriptMITCreated 2019-04-09zustand-demo.pmnd.rs/
58,909
stars
+2
2,191
forks
190
watchers
1,240
prs
699
issues
107
releases
1,528
discussions

README

A small, fast and scalable bearbones state-management solution using simplified flux principles. Has a comfy API based on hooks, isn't boilerplatey or opinionated.

Don't disregard it because it's cute. It has quite the claws, lots of time was spent dealing with common pitfalls, like the dreaded zombie child problem, react concurrency, and context loss between mixed renderers. It may be the one state-manager in the React space that gets all of these right.

You can try a live demo and read the docs.

bash
npm install zustand


:warning: This readme is written for JavaScript users. If you are a TypeScript user, be sure to check out our TypeScript Usage section.

 First create a store

Your store is a hook! You can put anything in it: primitives, objects, functions. State has to be updated immutably and the set function merges state to help it.

jsx
import { create } from 'zustand'

const useBearStore = create((set) = ({
  bears: 0,
  increasePopulation: () = set((state) = ({ bears: state.bears + 1 })),
  removeAllBears: () = set({ bears: 0 }),
}))


 Then bind your components, and that's it!

Use the hook anywhere, no providers are needed. Select your state and the component will re-render on changes.

jsx
function BearCounter() {
  const bears = useBearStore((state) = state.bears)
  return {bears} around here ...
}

function Controls() {
  const increasePopulation = useBearStore((state) = state.increasePopulation)
  return one up
}


 Why zustand over redux?

- Simple and un-opinionated
- Makes hooks the primary means of consuming state
- Doesn't wrap your app in context providers
- Can inform components transiently (without causing render)

 Why zustand over context?

- Less boilerplate
- Renders components only on changes
- Centralized, action-based state management

---

 Recipes

 Fetching everything

You can, but bear in mind that it will cause the component to update on every state change!

jsx
const state = useBearStore()


 Selecting multiple state slices

It detects changes with strict-equality (old === new) by default, this is efficient for atomic state picks.

jsx
const nuts = useBearStore((state) = state.nuts)
const honey = useBearStore((state) = state.honey)


If you want to construct a single object with multiple state-picks inside, similar to redux's mapStateToProps, you can use useShallow to prevent unnecessary rerenders when the selector output does not change according to shallow equal.

jsx
import { create } from 'zustand'
import { useShallow } from 'zustand/react/shallow'

const useBearStore = create((set) = ({
  nuts: 0,
  honey: 0,
  treats: {},
  // ...
}))

// Object pick, re-renders the component when either state.nuts or state.honey change
const { nuts, honey } = useBearStore(
  useShallow((state) = ({ nuts: state.nuts, honey: state.honey })),
)

// Array pick, re-renders the component when either state.nuts or state.honey change
const [nuts, honey] = useBearStore(
  useShallow((state) = [state.nuts, state.honey]),
)

//

Top issues

Discussions

Latest release

v5.1.0 v5.1.0 2026-11-06
The persist and devtools middleware are improved thanks to @Tnalxmsk and @dgesteves!

 Release note

- The persist middleware now supports PromiseLike results from storage reads, migrations, and migration writes. persist.rehydrate() now returns a native Promise, which you can await to ensure hydration is complete.
- The devtools middleware now supports dispatching store actions directly from Redux DevTools using the new actionCreators option. It also supports nested actions and arguments.

 What's Changed
 fix(middleware): persist migration supporting promise-like by @dai-shi in https:

Snapshot: 2026-11-10T09:35:25Z · Data license Apache-2.0 · JSON