mrkeyoor.com_
Sun 20 Sept 11:43 UTC
npmWeb Frontendupdated 20 Sept 2026

reselect review

Reselect 5.3.0 creates memoized selectors from plain input functions and a result function, most often for Redux state. When extracted input references stay equal, the selector returns its existing result without recomputing, which also preserves reference equality for React-Redux. Version 5.3 adds maxSize to the default weakMapMemoize, a development warning for growing caches, faster cache-hit paths, and a TypeScript 5.6 floor. It removes the experimental unstable_autotrackMemoize export. Bounding createSelector requires limits on both its argument cache and result-function cache.

36.5Mdownloads / wk
Verdict

Reselect 5.3.0 installed in 0.4 seconds and bundled to 2.1 KB gzipped in our sandbox, so measured cost is low when derived-reference stability saves real work. Skip it for trivial property reads, mutable state, or Redux Toolkit projects that already receive createSelector.

We installed it

Lab card: what happened when we installed reselectScreenshot of reselect documentation
Install✓ · 0.4s1 package on disk · 1 MB
ImportESM import works · require() works · CommonJS package with exports map
Browser2.1 KBgzipped (4.7 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does reselect install cleanly?

Yes. In a fresh container with an empty cache, npm install reselect finished in 0.4s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does reselect add to a browser bundle?

2.1 KB gzipped (4.7 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does reselect work with both ESM and CommonJS?

Yes. Both import 'reselect' and require('reselect') worked in Node 22 in our run. The package is published as CommonJS with an exports map.

Does reselect include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

reselect or proxy-memoize: which should you use?

Pick proxy-memoize when proxy-memoize 3.x fits when property-access tracking should decide which nested changes invalidate derived state. Reselect 5.3.0 installed in 0.4 seconds and bundled to 2.1 KB gzipped in our sandbox, so measured cost is low when derived-reference stability saves real work.

When should you not use reselect?

Redux Toolkit is already installed only for Redux code. It exports createSelector, so a separate reselect dependency usually adds no API.

API stability4/5createSelector, arrays of input selectors, result functions, createSelectorCreator, and recomputation counters remain the recognizable public model. Version 5 changed the default memoizer and version 5.3 removes unstable_autotrackMemoize, raises TypeScript support to 5.6, and adds two-level cache-bound guidance. Stable APIs are solid, but code depending on experimental exports or undocumented cache behavior needs migration work.
Docs5/5reselect.js.org has API and usage pages for createSelector, custom creators, weakMapMemoize, lruMemoize, development checks, TypeScript, FAQ cases, and common mistakes. The 5.3 documentation explains generational maxSize behavior, separate argument and result caches, and the two calls needed for a full clear. Redux's deriving-data guide supplies the application context that an API reference alone would miss.
Maintenance5/5npm published 5.3.0 on August 22, 2026, and the GitHub repository was pushed the same day. It is unarchived with 19,018 stars and 36 open issues and pull requests. The release includes memory test infrastructure, cache correctness fixes, benchmark revisions, faster hot paths, type fixes, and expanded documentation, giving both performance claims and cache behavior explicit tests.
Ecosystem5/5npm counted 45,724,116 downloads in the latest completed week, while GitHub reports 19,018 stars. Redux Toolkit exports createSelector and React-Redux patterns commonly depend on stable selector results, giving Reselect reach beyond direct installs. It also works with plain immutable JavaScript data. The ecosystem advantage is weaker when an application already has another memoization model or relies on mutable stores.

Discussed on

  1. hnRe-re-reselect: Simplifying React state management22 points
  2. hnReact and Reselect – Memoized Selectors for Efficient Rendering4 points
  3. hnHow We Reselect and You Can Too3 points

Use it if

  • Reselect 5.3.0 fits state derivations that are expensive enough or return references whose stability matters to React rendering.
  • Parameterized selectors need several cached argument combinations rather than the single-entry behavior used before Reselect 5.
  • A team wants recomputation counters and development checks to diagnose unstable selector inputs.
  • Redux Toolkit is not already the dependency supplying createSelector, or the standalone package is intentionally used outside Redux.
Skip it if

Setup reality

We installed reselect 5.3.0 in a fresh Node 22 Bookworm sandbox. npm completed in 0.4 seconds, left 1 package, and used 1 MB. npm audit reported 0 known vulnerabilities. The package has 0 direct and 0 peer dependencies, with 732 KB unpacked. It includes TypeScript declarations. package.json describes CommonJS with an exports map, and both require() and ESM import worked under Node 22.23.2.

Our broad browser import measured 4.7 KB minified and 2.1 KB gzipped in esbuild. If a project already uses Redux Toolkit, import createSelector from @reduxjs/toolkit rather than installing this package again. Outside Redux, selectors work with any immutable input objects. The important word is immutable: changing an array in place keeps its reference and can leave a cached result stale.

Input selectors receive every call argument and should only extract values. Put filtering, mapping, sorting, and object creation in the result function. A new array created inside an input selector defeats reference-based memoization. Use recomputations() and dependencyRecomputations() to distinguish a changing result input from changing selector arguments. Development stability checks can identify both an unstable input and an identity result function.

Version 5.3's weakMapMemoize maxSize uses generational cache swaps, not least-recently-used eviction. A createSelector output has two memoization levels, so set memoizeOptions.maxSize and argsMemoizeOptions.maxSize when both must be bounded. Use lruMemoize when eviction order or result equality is required. Fully clearing a selector also takes two calls: clearCache() and memoizedResultFunc.clearCache().

Patterns

Memoize a filtered collection filter-list

import { createSelector } from 'reselect';

const selectTodos = (state) => state.todos;
export const selectOpenTodos = createSelector([selectTodos], (todos) => todos.filter((todo) => !todo.done));

Filtering belongs in the result function. Returning a new array from selectTodos would force recomputation on every call.

Pass an entity ID as an argument select-by-id

const selectItems = (state) => state.items;
const selectId = (_state, id) => id;

export const selectItem = createSelector([selectItems, selectId], (items, id) => items[id]);

Every input selector receives every argument. Their parameter positions must remain compatible even when state is unused.

Create selectors pre-typed for RootState type-selectors

import { createSelector } from 'reselect';
import type { RootState } from './store';

export const createAppSelector = createSelector.withTypes<RootState>();
export const selectNames = createAppSelector([(state) => state.users], (users) => users.map((user) => user.name));

Array-form input selectors give withTypes the strongest inference. Reselect 5.3 supports TypeScript 5.6 and newer.

Bound both selector cache levels bound-cache

const selectWindow = createSelector(
  [selectItems, (_state, start) => start, (_state, _start, end) => end],
  (items, start, end) => items.slice(start, end),
  { memoizeOptions: { maxSize: 100 }, argsMemoizeOptions: { maxSize: 100 } },
);

Version 5.3 keeps separate argument and result caches. weakMapMemoize swaps generations at the limit rather than evicting one LRU item.

Choose least-recently-used eviction use-lru

import { createSelector, lruMemoize } from 'reselect';

const selectIds = createSelector([selectTodos], (todos) => todos.map((todo) => todo.id), {
  memoize: lruMemoize,
  memoizeOptions: { maxSize: 8 },
});

lruMemoize is the documented choice when eviction order matters. Keep the cache smaller than the argument diversity you truly reuse.

Separate argument churn from result work inspect-recomputations

selectOpenTodos(state);
selectOpenTodos(state);
console.log({
  results: selectOpenTodos.recomputations(),
  dependencies: selectOpenTodos.dependencyRecomputations(),
});

Rising dependency counts point to changing arguments or unstable inputs. Rising result counts mean extracted values changed.

Run selector diagnostics repeatedly enable-checks

const selectSummary = createSelector([(state) => state.orders], summarize, {
  devModeChecks: { inputStabilityCheck: 'always', identityFunctionCheck: 'always' },
});

always adds development work on each call. Return to the default once behavior after diagnosing the selector.

Clear both memoization layers clear-cache

selectOpenTodos.clearCache();
selectOpenTodos.memoizedResultFunc.clearCache();

Reselect 5.3 documents both calls. Clearing only the outer cache can leave the result-function cache populated.

Alternatives

PackageRegistryPick it when
proxy-memoizenpmproxy-memoize 3.x fits when property-access tracking should decide which nested changes invalidate derived state.
memoize-onenpmUse memoize-one when a general function only needs its most recent argument tuple cached.
micro-memoizenpmUse micro-memoize for configurable function memoization when Redux selector composition and diagnostics are unnecessary.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.