Stable computed arrays
A selector returns Object.keys(state), producing a fresh array while the set of keys stays unchanged.
Zustand · Function
useShallow is a React Hook for memoizing Zustand selector results with shallow comparison. It helps prevent unnecessary re-renders when computed objects or arrays are shallowly unchanged.
useShallow wraps a selector and returns a memoized selector. It uses shallow comparison on the selector result, so React components subscribed to computed objects or arrays can avoid re-rendering when their top-level values have not changed.
useShallow<T, U = T>(selectorFn: (state: T) => U): (state: T) => U| Name | Type | Description |
|---|---|---|
selectorFn | (state: T) => U | Selector function that receives the current state and returns the selected or derived value. |
A memoized selector function with type (state: T) => U; its result is memoized using shallow comparison.
import { create } from 'zustand'
import { useShallow } from 'zustand/react/shallow'
const useMeals = create(() => ({
papaBear: 'large porridge-pot',
mamaBear: 'middle-size porridge pot',
littleBear: 'A little, small, wee pot',
}))
export function BearNames() {
const names = useMeals(useShallow((state) => Object.keys(state)))
return <div>{names.join(', ')}</div>
}The selector creates an array of store keys; useShallow keeps the returned reference stable when those keys are shallowly unchanged.
A selector returns Object.keys(state), producing a fresh array while the set of keys stays unchanged.
A component selects several fields through a newly created object wrapper.
useShallow takes a selector function and returns a memoized selector. The memoized selector uses shallow comparison on the selector result, allowing a subscribed component to keep a stable result when its top-level values have not changed.
Follow-up: How does this differ from selecting a primitive? A primitive selector is already compared by value through the store subscription mechanism, while useShallow is useful for newly created object or array results.
The selector receives the current store state and returns derived data. Wrapping it with useShallow compares the derived result shallowly, so unchanged top-level values do not force the component to re-render.
Follow-up: What limitation follows from shallow comparison? Nested objects are not compared deeply, so changing a nested reference can be significant even if nested contents appear similar.
A common case is a selector such as Object.keys(state), which creates a fresh array on evaluation. useShallow lets the component avoid re-rendering when the resulting keys are shallowly equal to the previous keys.
Follow-up: What should be checked before using it? Verify that the selector output is repeatedly recreated but shallowly equivalent; otherwise ordinary selector subscription behavior may be sufficient.
shallowuseStorecreate