Selector
Problem
Components re-render unnecessarily when accessing derived data from state, even when the specific slice they need hasn’t changed. Transforming store data in render functions repeats expensive computations. Every state update triggers recalculations across all subscribed components. Components can’t efficiently subscribe to just the portion of state they actually need.
Solution
Derive computed values from state using memoized selectors that only recalculate when dependencies change. This improves performance and keeps derivation logic reusable and testable.
Example
This demonstrates using memoized selectors to derive computed values from state, preventing unnecessary recalculations and re-renders when dependencies haven’t changed.
// Create a memoized selector that only recalculates when users array changes
const selectActiveUsers = createSelector(
state => state.users, // Input selector - dependency
users => users.filter(u => u.isActive) // Transform function - only runs if users changed
);
// Use the selector - returns cached result if users haven't changed
const activeUsers = selectActiveUsers(state);
Benefits
- Prevents unnecessary recalculations by memoizing derived values.
- Reduces re-renders by only updating when relevant state slices change.
- Makes derivation logic reusable across components.
- Simplifies testing by isolating data transformation logic.
Tradeoffs
- Adds library dependency for selector creation and memoization.
- Can be overkill for simple derivations that are already fast.
- Requires understanding memoization and dependency tracking.
- May create complex dependency chains that are hard to debug.