Back to Reselect

lruMemoize

website/docs/api/lruMemoize.mdx

5.1.17.7 KB
Original Source

import Tabs from '@theme/Tabs' import TabItem from '@theme/TabItem' import { InternalLinks } from '@site/src/components/InternalLinks' import { ExternalLinks } from '@site/src/components/ExternalLinks'

lruMemoize

A memoization function that uses a provided equality check function to compare its inputs. This was originally known as defaultMemoize, and was the default inside of <InternalLinks.CreateSelector /> up through version 4.x.

It has a default cache size of 1. This means it always recalculates when the value of an argument changes. However, this can be customized as needed with a specific max cache size (since 4.1.0).

It determines if an argument has changed by calling the equalityCheck function. As lruMemoize is designed to be used with immutable data, the default equalityCheck function checks for changes using <ExternalLinks.ReferenceEqualityCheck text="reference equality" />:

<Tabs groupId='language' defaultValue='ts' values={[ {label: 'TypeScript', value: 'ts'}, {label: 'JavaScript', value: 'js'}, ]}> <TabItem value='ts'>

ts
const referenceEqualityCheck = (previousValue: any, currentValue: any) => {
  return previousValue === currentValue
}
</TabItem> <TabItem value='js'>
js
const referenceEqualityCheck = (previousValue, currentValue) => {
  return previousValue === currentValue
}
</TabItem> </Tabs>

Parameters

NameDescription
funcThe function to be memoized.
equalityCheckOrOptionsEither an equality check function or an options object.

Since 4.1.0, lruMemoize also accepts an options object as its first argument instead of an equalityCheck function. The options object may contain:

ts
type EqualityFn<T = any> = (a: T, b: T) => boolean

interface LruMemoizeOptions<Result = any> {
  equalityCheck?: EqualityFn
  resultEqualityCheck?: EqualityFn<Result>
  maxSize?: number
}
NameDescription
equalityCheckUsed to compare the individual arguments of the provided calculation function.
Default = defaultEqualityCheck
resultEqualityCheckIf provided, used to compare a newly generated output value against previous values in the cache. If a match is found, the old value is returned. This addresses the common <code>todos.map(todo => todo.id)</code> use case, where an update to another field in the original data causes a recalculation due to changed references, but the output is still effectively the same.
maxSizeThe cache size for the selector. If greater than 1, the selector will use an LRU cache internally.
Default = 1

:::warning

If resultEqualityCheck is used inside argsMemoizeOptions it has no effect.

:::

Returns

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

Type Parameters

NameDescription
FuncThe type of the function that is memoized.

Examples

Using lruMemoize with createSelector

<Tabs groupId='language' defaultValue='ts' values={[ {label: 'TypeScript', value: 'ts'}, {label: 'JavaScript', value: 'js'}, ]}> <TabItem value='ts'>

ts
import { shallowEqual } from 'react-redux'
import { createSelector, lruMemoize } from 'reselect'

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

const selectTodoIds = createSelector(
  [(state: RootState) => state.todos],
  todos => todos.map(todo => todo.id),
  {
    memoize: lruMemoize,
    memoizeOptions: {
      equalityCheck: shallowEqual,
      resultEqualityCheck: shallowEqual,
      maxSize: 10
    },
    argsMemoize: lruMemoize,
    argsMemoizeOptions: {
      equalityCheck: shallowEqual,
      resultEqualityCheck: shallowEqual,
      maxSize: 10
    }
  }
)
</TabItem> <TabItem value='js'>
js
import { shallowEqual } from 'react-redux'
import { createSelector, lruMemoize } from 'reselect'

const selectTodoIds = createSelector(
  [state => state.todos],
  todos => todos.map(todo => todo.id),
  {
    memoize: lruMemoize,
    memoizeOptions: {
      equalityCheck: shallowEqual,
      resultEqualityCheck: shallowEqual,
      maxSize: 10
    },
    argsMemoize: lruMemoize,
    argsMemoizeOptions: {
      equalityCheck: shallowEqual,
      resultEqualityCheck: shallowEqual,
      maxSize: 10
    }
  }
)
</TabItem> </Tabs>

Using lruMemoize with createSelectorCreator

<Tabs groupId='language' defaultValue='ts' values={[ {label: 'TypeScript', value: 'ts'}, {label: 'JavaScript', value: 'js'}, ]}> <TabItem value='ts'>

ts
import { shallowEqual } from 'react-redux'
import { createSelectorCreator, lruMemoize } from 'reselect'

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

const createSelectorShallowEqual = createSelectorCreator({
  memoize: lruMemoize,
  memoizeOptions: {
    equalityCheck: shallowEqual,
    resultEqualityCheck: shallowEqual,
    maxSize: 10
  },
  argsMemoize: lruMemoize,
  argsMemoizeOptions: {
    equalityCheck: shallowEqual,
    resultEqualityCheck: shallowEqual,
    maxSize: 10
  }
})

const selectTodoIds = createSelectorShallowEqual(
  [(state: RootState) => state.todos],
  todos => todos.map(todo => todo.id)
)
</TabItem> <TabItem value='js'>
js
import { shallowEqual } from 'react-redux'
import { createSelectorCreator, lruMemoize } from 'reselect'

const createSelectorShallowEqual = createSelectorCreator({
  memoize: lruMemoize,
  memoizeOptions: {
    equalityCheck: shallowEqual,
    resultEqualityCheck: shallowEqual,
    maxSize: 10
  },
  argsMemoize: lruMemoize,
  argsMemoizeOptions: {
    equalityCheck: shallowEqual,
    resultEqualityCheck: shallowEqual,
    maxSize: 10
  }
})

const selectTodoIds = createSelectorShallowEqual(
  [state => state.todos],
  todos => todos.map(todo => todo.id)
)
</TabItem> </Tabs>