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
zustand redux
Taught by the skill
fe-state State and stores
Since version
0.1.0

Rule file on GitHub

Read it in the terminal

npx github:dawidolko/frontend-skills explain state/selector-stable-result