Skip to content

Releases: pmndrs/zustand

v3.1.2

12 Sep 11:59
Compare
Choose a tag to compare

This patch release adds an improvement in devtools middleware.

v3.1.1

08 Sep 13:14
Compare
Choose a tag to compare

Bug fixes

Doc fixes

v3.1.0

03 Sep 13:16
Compare
Choose a tag to compare

This release is mainly for TypeScript users.

The base State type is stricter.

In v3.0.3:
image

In v3.1.0:
image

To fix it:
image

See also:

New combine middleware

This will combine two parts of state into one. The first part is primitive state, and the second part is actions that depend on set.

image

The resulting type is inferred from the state creator.

image

v3.0.3

14 Oct 14:41
Compare
Choose a tag to compare

This fixes a bug in devtools middleware.

v3.0.2

14 Oct 14:35
Compare
Choose a tag to compare

This fixes some issues in middleware.

BREAKING CHANGE in devtools: set now requires replace introduced in v3 api. ref: #159 (comment)

Zustand 3.x

17 Aug 20:04
Compare
Choose a tag to compare

What's new

First of all, this release is 100% backward compatible, it will not break your code! The only breaking change (the create functions return value) still can work in the old way, but throws a small deprecation warning.

Our main focus has been:

  • Stability and fixing bugs
  • Making it suitable for concurrent mode
  • Supporting React-fast-refresh
  • Making it more versatile so that it can be used without React

We will soon publish an experimental V4 that utilizes react-experimentals useMutableSource in concurrent mode. The groundwork for this has been laid in this major.

Simpler API

import create from 'zustand'

const useStore = create(set => ({
  bears: 0,
  increasePopulation: () => set(state => ({ count: state.bears + 1 })),
  resetPopulation: () => set({ bears: 0 })
}))

function BearCounter() {
  const bears = useStore(state => state.bears)
  return <h1>{bears} around here ...</h1>
}

function Controls() {
  const increasePopulation = useStore(state => state.increasePopulation)
  return <button onClick={increasePopulation}>one up</button>
}

Utility functions are on the hooks prototype

Sometimes you need to access the state in a non-reactive way, or act upon the store. For these cases the resulting hook has utility functions attached to its prototype.

const useStore = create(() => ({ paw: true, snout: true, fur: true }))

// Getting non-reactive fresh state
const paw = useStore.getState().paw
// Listening to all changes, fires on every change
const unsub1 = useStore.subscribe(console.log)
// Listening to selected changes, in this case when "paw" changes
const unsub2 = useStore.subscribe(console.log, state => state.paw)
// Updating state, will trigger listeners
useStore.setState({ paw: false })
// Unsubscribe listeners
unsub1()
unsub2()
// Destroying the store (removing all listeners)
useStore.destroy()

// You can of course use the hook as you always would
function Component() {
  const paw = useStore(state => state.paw)

Using zustand without React

Zustands core can be imported and used without the React dependency. The only difference is that the create function does not return a hook, but the api utilities.

import create from 'zustand/vanilla'

const store = create(() => ({ ... }))
const { getState, setState, subscribe, destroy } = store

You can even consume an existing vanilla store with React:

import create from 'zustand'
import vanillaStore from './vanillaStore'

const useStore = create(vanillaStore)

Overwriting state

The set function has a second argument, false by default. Instead of merging, it will replace the state model. Be careful not to wipe out parts you rely on, like actions.

import omit from "lodash-es/omit"

const useStore = create(set => ({
  salmon: 1,
  tuna: 2,
  deleteEverything: () => set({ }), true), // clears the entire store, actions included
  deleteTuna: () => set(state => omit(state, ['tuna']), true)
}))

v2.2.0

24 Oct 14:15
Compare
Choose a tag to compare

2.2.0

v2.1.0

11 Oct 16:49
d82e103
Compare
Choose a tag to compare
  • Removed SubscribeOptions and UseStoreSubscribeOptions types.
  • Added Subscriber type.
  • Improve performance by consolidating subscribers sparse array.
  • Fix potential issue with concurrent mode.

v2.0.0

11 Oct 16:47
e77ab24
Compare
Choose a tag to compare
  • Removed ESM and IIFE versions of middleware.js and shallow.js. Any imports of the ".cjs" files should be changed from "zustand/{name}.cjs" to just "zustand/{name}" as they are all CommonJS now (index.js still has different formats).
  • api.subscribe has a new function signature that removes the object wrapper: api.subscribe(listener, selector?, equalityFn?).
  • StateListener type has changed. An overloaded signature was added for better error handling.
  • Subscribe type has changed. It uses the updated StateListener type.
  • listeners are iterated in a different order than they were before. Parent to child rather than child to parent. It would be rare if this causes any issues.
  • The automatic fix when passing an array as the second arg of useStore was removed. useStore will throw an Uncaught TypeError if the second arg is an array.