Skip to main content


Uses an "auto-tracking" approach inspired by the work of the Ember Glimmer team. It uses a Proxy to wrap arguments and track accesses to nested fields in your selector on first read. Later, when the selector is called with new arguments, it identifies which accessed fields have changed and only recalculates the result if one or more of those accessed fields have changed. This allows it to be more precise than the shallow equality checks in lruMemoize.


This API is still experimental and undergoing testing.

Design Tradeoffs

  • Pros:

    • It is likely to avoid excess calculations and recalculate fewer times than lruMemoize will, which may also result in fewer component re-renders.
  • Cons:

    • It only has a cache size of 1.
    • It is slower than lruMemoize, because it has to do more work. (How much slower is dependent on the number of accessed fields in a selector, number of calls, frequency of input changes, etc)
    • It can have some unexpected behavior. Because it tracks nested field accesses, cases where you don't access a field will not recalculate properly. For example, a badly-written selector like:
    createSelector([state => state.todos], todos => todos)

    that just immediately returns the extracted value will never update, because it doesn't see any field accesses to check.

Use Cases

  • It is likely best used for cases where you need to access specific nested fields in data, and avoid recalculating if other fields in the same data objects are immutably updated.


funcThe function to be memoized.


A memoized function with a .clearCache() method attached.

Type Parameters

FuncThe type of the function that is memoized.


Using unstable_autotrackMemoize with createSelector

import { createSelector, unstable_autotrackMemoize } from 'reselect'

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

const selectTodoIds = createSelector(
[(state: RootState) => state.todos],
todos => =>,
{ memoize: unstable_autotrackMemoize }

Using unstable_autotrackMemoize with createSelectorCreator

import { createSelectorCreator, unstable_autotrackMemoize } from 'reselect'
import type { RootState } from './usingWithCreateSelector'

const createSelectorAutotrack = createSelectorCreator({
memoize: unstable_autotrackMemoize

const selectTodoIds = createSelectorAutotrack(
[(state: RootState) => state.todos],
todos => =>