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)
}))