Documentation Index
Fetch the complete documentation index at: https://mintlify.com/iDevRanjan/nexus-store/llms.txt
Use this file to discover all available pages before exploring further.
useStore accepts a selector function as its second argument. That selector is called on every store notification to determine whether the subscribed component should re-render — React compares the previous and next return values and skips the render if they are equal. The selector function itself, however, is also part of the subscription equation: useStore internally wraps it in useCallback, so if the selector reference changes between renders, the subscription is rebuilt unnecessarily. For most apps this is imperceptible, but in large component trees with high update frequency it adds up. The fix is simple — keep your selector reference stable.
The Problem with Inline Selectors
When a selector is written as an inline arrow function, JavaScript creates a brand-new function object on every render. The function body is identical, but the reference is different:Inline selector — new reference on every render
cart.items actually changes — but the subscription rebuilds on every render because useStore sees a different selector reference each time. For small apps this is fine. In a large tree it creates unnecessary overhead.
Solution 1: Module-Level Selector (Recommended)
Define the selector outside the component at module scope. A module-level function is created once when the module loads and its reference never changes, regardless of how many times the component re-renders.Module-level selector — zero reference churn
CartComponent.jsx in the source:
src/components/CartComponent.jsx (module-level selector)
Solution 2: useCallback
When a selector must be defined inside the component — for example because it closes over a prop or local variable — wrap it with useCallback so React memoizes the reference across renders.
CartComponent in the source uses this pattern as its active implementation:
src/components/CartComponent.jsx
[] means the selector reference is created once and reused for the component’s entire lifetime — identical behaviour to a module-level selector, just scoped to the component instance.
When the selector does close over a changing value, list that value in the dependency array so the selector updates when needed:
Selector that closes over a prop
Anti-Pattern: Inline Selector
The inline form is not wrong — it will keep your component data-correct. It is simply not optimal for frequently-rendering components in large applications.Inline selector — functionally correct, not optimal at scale
For most apps with a moderate number of components, inline selectors are perfectly acceptable. Reach for module-level selectors or
useCallback when React DevTools Profiler shows a component re-rendering more often than expected, or when you are building a library on top of NexusStore.Comparison
| Approach | Reference stability | When to use |
|---|---|---|
| Module-level selector | ✅ Always stable — defined once at module load | Default choice for any selector that does not need component-local variables |
useCallback selector | ✅ Stable until deps change | Selector that closes over props or state local to the component |
| Inline selector | ❌ New reference every render | Prototyping, small apps, or when profiling confirms it is not a bottleneck |