State
state/selector-stable-result
A store selector returns existing values, not a new object or array on every call; pick fields one by one or use useShallow or shallowEqual.
seriousstaticfe-state
Why
A selector such as (s) => ({ count: s.count, user: s.user }) builds a new object each time it runs, so the store sees a "changed" result on every update. With React Redux the component re-renders after every dispatched action, wherever it happened. With Zustand 5, which compares with Object.is, the same selector can loop until React stops with "Maximum update depth exceeded".
Fix
Select one value per call (const count = useStore((s) => s.count)), or wrap a multi-value selector in useShallow (Zustand) or pass shallowEqual (React Redux). A derived list (s.todos.filter(...)) belongs in a memoized selector (createSelector) or is computed in the component from the raw slice.
Examples
// bad
const { count, inc } = useCounterStore((s) => ({ count: s.count, inc: s.inc }))
const done = useSelector((state) => state.todos.filter((t) => t.done))
// good
const [count, inc] = useCounterStore(useShallow((s) => [s.count, s.inc]))
const todos = useSelector((state) => state.todos)
const done = todos.filter((t) => t.done)Sources
Facts
- Id
state/selector-stable-result- Severity
- serious
- Check
- static checked in the source by
audit - Applies to
jsx- Only in projects with
zustandredux- Taught by the skill
fe-stateState and stores- Since version
- 0.1.0
Read it in the terminal
npx github:dawidolko/frontend-skills explain state/selector-stable-result