CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-reselect

Selectors for Redux - memoized functions for computing derived data from state.

Pending
Overview
Eval results
Files

selector-creation.mddocs/

Selector Creation

Core functionality for creating memoized selectors using the default createSelector function and customizable options.

Capabilities

createSelector

Creates a memoized selector that computes derived data from state. The selector will only recompute when one of its input selectors returns a different value.

/**
 * Creates a memoized selector from input selectors and a result function
 * @param selectors - Array of input selector functions
 * @param combiner - Function that combines the results of input selectors
 * @returns Memoized output selector with additional metadata
 */
function createSelector<State, Result>(
  selectors: SelectorArray<State>,
  combiner: (...args: any[]) => Result
): OutputSelector<State, Result>;

/**
 * Creates a memoized selector with custom options
 * @param selectors - Array of input selector functions  
 * @param combiner - Function that combines the results of input selectors
 * @param options - Configuration options for memoization and dev mode checks
 * @returns Memoized output selector with additional metadata
 */
function createSelector<State, Result>(
  selectors: SelectorArray<State>,
  combiner: (...args: any[]) => Result,
  options: CreateSelectorOptions
): OutputSelector<State, Result>;

/**
 * Variadic overload for inline input selectors
 * @param selector1 - First input selector
 * @param selector2 - Second input selector  
 * @param combiner - Function that combines selector results
 * @returns Memoized output selector
 */
function createSelector<State, Res1, Res2, Result>(
  selector1: Selector<State, Res1>,
  selector2: Selector<State, Res2>,
  combiner: (res1: Res1, res2: Res2) => Result
): OutputSelector<State, Result>;

// Additional overloads for 3-12 input selectors...

Basic Usage:

import { createSelector } from "reselect";

// Simple selector with two inputs
const selectShopItems = (state) => state.shop.items;
const selectTaxPercent = (state) => state.shop.taxPercent;

const selectSubtotal = createSelector(
  [selectShopItems],
  (items) => items.reduce((acc, item) => acc + item.price, 0)
);

const selectTax = createSelector(
  [selectSubtotal, selectTaxPercent],
  (subtotal, taxPercent) => subtotal * (taxPercent / 100)
);

const selectTotal = createSelector(
  [selectSubtotal, selectTax],
  (subtotal, tax) => ({ total: subtotal + tax })
);

With Custom Options:

import { createSelector, lruMemoize } from "reselect";

const selectExpensiveComputation = createSelector(
  [selectLargeDataset],
  (data) => computeExpensiveDerivation(data),
  {
    memoize: lruMemoize,
    memoizeOptions: { maxSize: 10 },
    devModeChecks: { inputStabilityCheck: 'always' }
  }
);

OutputSelector Interface

The enhanced selector returned by createSelector with additional metadata and methods.

interface OutputSelector<State, Result, Params extends readonly any[] = any[]> 
  extends Selector<State, Result, Params> {
  /** The original result function passed to createSelector */
  resultFunc: (...args: any[]) => Result;
  
  /** The memoization function used by this selector */
  memoize: UnknownMemoizer;
  
  /** The arguments memoization function used by this selector */
  argsMemoize: UnknownMemoizer;
  
  /** Array of input selectors used by this selector */
  dependencies: SelectorArray<State>;
  
  /** Returns the number of times the result function has been recomputed */
  recomputations: () => number;
  
  /** Resets the recomputation counter to 0 */
  resetRecomputations: () => void;
  
  /** Returns the number of times the dependencies have been recomputed */
  dependencyRecomputations: () => number;
  
  /** Resets the dependency recomputation counter to 0 */
  resetDependencyRecomputations: () => void;
  
  /** Returns the last computed result */
  lastResult: () => Result;
  
  /** The memoized version of the result function */
  memoizedResultFunc: (...args: any[]) => Result;
}

Usage Examples:

const mySelector = createSelector([selectA, selectB], (a, b) => a + b);

// Check recomputation counts
console.log(mySelector.recomputations()); // 0
console.log(mySelector.dependencyRecomputations()); // 0

// Use the selector
const result1 = mySelector(state); 
console.log(mySelector.recomputations()); // 1
console.log(mySelector.dependencyRecomputations()); // 1

// Same inputs won't recompute  
const result2 = mySelector(state);
console.log(mySelector.recomputations()); // Still 1
console.log(mySelector.dependencyRecomputations()); // Still 1

// Get the last result
console.log(mySelector.lastResult()); // The computed result

// Reset counters
mySelector.resetRecomputations();
mySelector.resetDependencyRecomputations();
console.log(mySelector.recomputations()); // 0
console.log(mySelector.dependencyRecomputations()); // 0

// Access the underlying result function
const directResult = mySelector.resultFunc(valueA, valueB);

CreateSelectorOptions

Configuration options for customizing selector behavior.

interface CreateSelectorOptions<MemoizeFunction = typeof weakMapMemoize> {
  /** Custom memoization function (defaults to weakMapMemoize) */
  memoize?: MemoizeFunction;
  
  /** Options passed to the memoization function */
  memoizeOptions?: ExtractMemoizerFields<MemoizeFunction>;
  
  /** Custom arguments memoization function (defaults to weakMapMemoize) */
  argsMemoize?: UnknownMemoizer;
  
  /** Options passed to the arguments memoization function */
  argsMemoizeOptions?: unknown[];
  
  /** Development mode check configuration */
  devModeChecks?: Partial<DevModeChecks>;
}

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';

Parametric Selectors

Selectors that accept additional parameters beyond state.

import { createSelector } from "reselect";

// Selector with parameters
const selectTodoById = createSelector(
  [(state, id) => state.todos, (state, id) => id],
  (todos, id) => todos.find(todo => todo.id === id)
);

// Usage with parameters
const todo = selectTodoById(state, 42);

// Factory pattern for parametric selectors
const makeSelectorTodosByStatus = () => createSelector(
  [(state, status) => state.todos, (state, status) => status],
  (todos, status) => todos.filter(todo => todo.status === status)
);

const selectCompletedTodos = makeSelectorTodosByStatus();
const completedTodos = selectCompletedTodos(state, 'completed');

Pre-Typed Selectors

Create pre-typed versions of createSelector with predefined state types to eliminate repetitive type annotations.

import { createSelector } from "reselect";

interface RootState {
  todos: { id: number; completed: boolean }[];
  alerts: { id: number; read: boolean }[];
}

// Create a pre-typed createSelector with RootState
export const createAppSelector = createSelector.withTypes<RootState>();

// Now you can use createAppSelector without specifying state types
const selectTodoIds = createAppSelector(
  [
    // Type of `state` is automatically set to `RootState`
    state => state.todos
  ],
  todos => todos.map(({ id }) => id)
);

const selectActiveAlerts = createAppSelector(
  [state => state.alerts],
  alerts => alerts.filter(alert => !alert.read)
);

Types

type Selector<State = any, Result = unknown, Params extends readonly any[] = any[]> = 
  (state: State, ...params: Params) => Result;

type SelectorArray<State = any> = readonly Selector<State>[];

type SelectorResultArray<Selectors extends SelectorArray> = {
  [Index in keyof Selectors]: Selectors[Index] extends Selector<any, infer Result> 
    ? Result 
    : never;
};

type Combiner<Result> = (...args: any[]) => Result;

type UnknownMemoizer = (func: AnyFunction, ...options: unknown[]) => AnyFunction;

type AnyFunction = (...args: any[]) => any;

Install with Tessl CLI

npx tessl i tessl/npm-reselect

docs

development.md

index.md

memoization.md

selector-creation.md

selector-creator.md

structured-selectors.md

tile.json