Releases: pmndrs/zustand
v3.1.2
v3.1.1
v3.1.0
This release is mainly for TypeScript users.
The base State
type is stricter.
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
.
The resulting type is inferred from the state creator.
v3.0.3
v3.0.2
Zustand 3.x
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
v2.1.0
v2.0.0
- 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 updatedStateListener
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.