Selective external rendering
An external renderer should update only when the position slice changes.
Zustand · Const
subscribeWithSelector adds selector-based subscriptions to a Zustand state creator. Listeners can react to changes in a selected slice, such as one nested field, instead of subscribing to the whole state.
Apply subscribeWithSelector to a Zustand state creator to add selector-based subscriptions. The store's subscribe method then accepts a selector and listener, so the listener responds to changes in the selected result rather than every complete state update; the subscription returns an unsubscribe function.
subscribeWithSelector<T>(stateCreatorFn: StateCreator<T, [], []>): StateCreator<T, [['zustand/subscribeWithSelector', never]], []>| Name | Type | Description |
|---|---|---|
stateCreatorFn | StateCreator<T, [], []> | A function receiving set, get, and store, usually returning the state and actions exposed by the store. |
A state creator function with selector-enabled subscriptions.
import { createStore } from 'zustand/vanilla'
import { subscribeWithSelector } from 'zustand/middleware'
type Position = { x: number; y: number }
type PositionStore = {
position: Position
setPosition: (position: Position) => void
}
const positionStore = createStore<PositionStore>()(
subscribeWithSelector((set) => ({
position: { x: 0, y: 0 },
setPosition: (position) => set({ position }),
})),
)
const unsubscribe = positionStore.subscribe(
(state) => state.position.x,
(x) => console.log('x changed:', x),
)
positionStore.getState().setPosition({ x: 10, y: 5 })
unsubscribe()Creates a vanilla store enhanced with subscribeWithSelector, then observes only the position's x coordinate until the returned unsubscribe function is called.
An external renderer should update only when the position slice changes.
A logger should record changes to one field rather than every store update.
A service needs to react to a small portion of state outside React.
Wrap the state creator with subscribeWithSelector before passing it to createStore or another store creator. This augments subscribe so it can receive a selector and listen to partial state updates.
Follow-up: How would you observe only one nested field? Pass a selector such as state => state.position.x, then handle that selected value in the listener.
The middleware accepts a state creator function and returns another state creator function. The state creator receives set, get, and store, and normally returns the store's exposed state and actions.
Follow-up: What is the middleware's TypeScript shape? It transforms StateCreator<T, [], []> into StateCreator<T, [['zustand/subscribeWithSelector', never]], []>.
Call store.subscribe with a selector as the first argument and the listener as the second. The listener is invoked for updates to the selected portion, and subscribe returns a function for ending the subscription.
Follow-up: How could a subscription support an external renderer? Select the renderable slice and use the listener to trigger rendering whenever that slice updates.
createStoresubscribeStateCreatorsetgetstore