Selectors for Redux - memoized functions for computing derived data from state.
—
Development-only stability checks and debugging utilities to help identify common selector issues and ensure optimal performance.
Configures global development mode check settings for all selectors in the application.
/**
* Overrides the development mode checks settings for all selectors
* @param devModeChecks - Partial configuration object for dev mode checks
*/
function setGlobalDevModeChecks(devModeChecks: Partial<DevModeChecks>): void;
interface DevModeChecks {
/** Check for unstable input selector results */
inputStabilityCheck: DevModeCheckFrequency;
/** Check if result function is an identity function */
identityFunctionCheck: DevModeCheckFrequency;
}
type DevModeCheckFrequency = 'once' | 'always' | 'never';Basic Usage:
import { setGlobalDevModeChecks } from "reselect";
// Run checks only on first selector call (default)
setGlobalDevModeChecks({
inputStabilityCheck: 'once',
identityFunctionCheck: 'once'
});
// Run checks on every selector call
setGlobalDevModeChecks({
inputStabilityCheck: 'always',
identityFunctionCheck: 'always'
});
// Disable specific checks
setGlobalDevModeChecks({
inputStabilityCheck: 'never',
identityFunctionCheck: 'once'
});
// Partial configuration (unspecified settings retain current values)
setGlobalDevModeChecks({
inputStabilityCheck: 'always'
// identityFunctionCheck keeps its current setting
});Development mode checks help identify common selector performance issues and mistakes.
Input Stability Check:
Identity Function Check:
Override global settings for specific selectors using CreateSelectorOptions.
import { createSelector } from "reselect";
// Override global settings for specific selector
const selectSpecialData = createSelector(
[selectInputData],
(data) => processData(data),
{
devModeChecks: {
inputStabilityCheck: 'always', // Always check this selector
identityFunctionCheck: 'never' // Never check identity for this one
}
}
);
// Disable all checks for performance-critical selector
const selectCriticalPath = createSelector(
[selectLargeDataset],
(data) => criticalProcessing(data),
{
devModeChecks: {
inputStabilityCheck: 'never',
identityFunctionCheck: 'never'
}
}
);Unstable Input Selectors:
import { createSelector } from "reselect";
// ❌ BAD: Creates new array on every call
const selectBadItems = (state) => state.items.filter(item => item.active);
// ✅ GOOD: Stable input selector
const selectItems = (state) => state.items;
const selectActiveFilter = (state) => true; // or from actual filter state
const selectActiveItems = createSelector(
[selectItems, selectActiveFilter],
(items, shouldFilterActive) =>
shouldFilterActive ? items.filter(item => item.active) : items
);Identity Function Issues:
import { createSelector } from "reselect";
// ❌ BAD: Identity function - just returns first argument
const selectBadUser = createSelector(
[(state) => state.user],
(user) => user // This is an identity function
);
// ✅ GOOD: Actually transforms the data
const selectUserDisplayName = createSelector(
[(state) => state.user],
(user) => user ? `${user.firstName} ${user.lastName}` : 'Anonymous'
);
// ✅ ALSO GOOD: Direct selector when no transformation needed
const selectUser = (state) => state.user;Information about development mode check execution (internal type).
interface DevModeChecksExecutionInfo {
/** Information about input stability check execution */
inputStabilityCheck: DevModeCheckExecutionInfo;
/** Information about identity function check execution */
identityFunctionCheck: DevModeCheckExecutionInfo;
}
interface DevModeCheckExecutionInfo {
/** Whether the check should run */
shouldRun: boolean;
/** Number of times this check has been executed */
timesRun: number;
}Development mode checks are automatically disabled in production builds to ensure optimal performance.
// Development mode checks only run when process.env.NODE_ENV !== 'production'
// In production, these checks are completely bypassed for performance
import { createSelector, setGlobalDevModeChecks } from "reselect";
// This configuration only affects development builds
setGlobalDevModeChecks({ inputStabilityCheck: 'always' });
const selectData = createSelector(
[selectInput],
(input) => processInput(input)
// Dev mode checks run in development, ignored in production
);Checking Recomputations:
import { createSelector } from "reselect";
const selectExpensiveData = createSelector(
[selectLargeDataset, selectFilters],
(data, filters) => expensiveProcessing(data, filters)
);
// Monitor recomputations in development
console.log('Recomputations:', selectExpensiveData.recomputations());
// Use the selector
const result = selectExpensiveData(state);
console.log('After use:', selectExpensiveData.recomputations());
// Reset counter for testing
selectExpensiveData.resetRecomputations();Custom Development Logging:
import { createSelector } from "reselect";
const selectWithLogging = createSelector(
[selectInput],
(input) => {
if (process.env.NODE_ENV === 'development') {
console.log('Selector recomputing with input:', input);
}
return processInput(input);
}
);import { createSelector, setGlobalDevModeChecks } from "reselect";
describe('Selector Tests', () => {
beforeEach(() => {
// Enable all checks for testing
setGlobalDevModeChecks({
inputStabilityCheck: 'always',
identityFunctionCheck: 'always'
});
});
it('should not recompute with same inputs', () => {
const selector = createSelector(
[(state) => state.data],
(data) => processData(data)
);
selector(state1);
const recomputations1 = selector.recomputations();
selector(state1); // Same state
const recomputations2 = selector.recomputations();
expect(recomputations2).toBe(recomputations1); // Should not increase
});
});interface DevModeChecks {
inputStabilityCheck: DevModeCheckFrequency;
identityFunctionCheck: DevModeCheckFrequency;
}
type DevModeCheckFrequency = 'once' | 'always' | 'never';
interface DevModeChecksExecutionInfo {
inputStabilityCheck: DevModeCheckExecutionInfo;
identityFunctionCheck: DevModeCheckExecutionInfo;
}
interface DevModeCheckExecutionInfo {
shouldRun: boolean;
timesRun: number;
}Install with Tessl CLI
npx tessl i tessl/npm-reselect