Blog>
Snippets

Debugging createSelector with Incorrect Memoization

Provide an example of a common mistake when using createSelector that leads to incorrect memoization, illustrate how to identify the issue, and correct it.
// Incorrectly created memoized selector that does not memoize properly
const getItems = state => state.items;
const selectItemsByFilter = createSelector(
  [getItems, (_, filter) => filter],
  (items, filter) => items.filter(item => item === filter)
);

// Usage of the selector function that might not be memoized correctly
const filteredItems = selectItemsByFilter(state, 'books');
console.log(filteredItems); // Incorrect memoization may cause the 'filter' function to run again unnecessarily
This code defines a memoized selector using createSelector. However, it uses a non-static parameter as an input (filter), leading to incorrect memoization because a new reference for the filter parameter is created every time, causing the selector to recompute.
// Corrected memoized selector to ensure proper memoization by avoiding the use of non-static parameters
const getItems = state => state.items;
const makeSelectItemsByFilter = filter => createSelector(
  [getItems],
  (items) => items.filter(item => item === filter)
);

// Correct usage of the selector by creating a memoized instance of the selector function
const selectItemsForBooks = makeSelectItemsByFilter('books');
const filteredItems = selectItemsForBooks(state);
console.log(filteredItems); // Proper memoization is achieved by creating a unique instance of the selector for each filter
This example corrects the previous issue by creating a 'selector factory' function, makeSelectItemsByFilter, which returns a new instance of a memoized selector for each specific filter value. This ensures that the memoization works correctly, as each instance of the selector maintains its own memoized result for the same filter value.