# Memoised Selectors with createSelector — Redux Toolkit / Zustand

Source: https://www.skillbyai.com/en/redux-zustand/p-selectors

> Derive data without needless re-renders.

## Compute once per input change

A selector that returns a new array, such as `state.todos.filter(...)`, produces a new reference on every call, so `useSelector` re-renders the component after every dispatched action. `createSelector` (from Reselect, re-exported by Redux Toolkit) takes **input selectors** and a **result function**; it recomputes only when the input results change by reference and otherwise returns the cached result. Keep raw state minimal and derive totals, filters and joins with selectors. Selectors that take arguments need care with cache size; check the Reselect docs for your version's memoisation defaults.

## Visible todos and a count

Composable memoised selectors.

```typescript
import { createSelector } from '@reduxjs/toolkit';

const selectFilter = (state: RootState) => state.todos.filter;

export const selectVisibleTodos = createSelector(
  [selectAllTodos, selectFilter],
  (todos, filter) => (filter === 'open' ? todos.filter((t) => !t.done) : todos)
);

export const selectOpenCount = createSelector(
  [selectAllTodos],
  (todos) => todos.filter((t) => !t.done).length
);

// component
const visible = useAppSelector(selectVisibleTodos); // same reference until inputs change
```

## Do not memoise trivial lookups

A selector like `(s) => s.user.name` already returns a stable value. Use createSelector when the result function creates new arrays or objects or does real work.

**Quiz:** When does a createSelector result function run again?

- [ ] Whenever any component re-renders
- [ ] On every call
- [ ] Only once at startup
- [x] When one of its input selector results changes by reference

*Answer:* When one of its input selector results changes by reference. Memoisation is keyed on input results.
