Reselect will not memoize correctly with multiple instances of the same component

I am reading documentation for Redux and stuck with reselect. The selector is created in the code below, and the documentation says that if we want to use it in two components VisibleTodoList, then it will not work correctly.

import { createSelector } from 'reselect'

const getVisibilityFilter = (state, props) => state.todoLists[props.listId].visibilityFilter

const getTodos = (state, props) => state.todoLists[props.listId].todos

const getVisibleTodos = createSelector([getVisibilityFilter, getTodos], (visibilityFilter, todos) => {
  switch (visibilityFilter) {
    case 'SHOW_COMPLETED':
      return todos.filter(todo => todo.completed)
    case 'SHOW_ACTIVE':
      return todos.filter(todo => !todo.completed)
    default:
      return todos
  }
})

export default getVisibleTodos

Using the getVisibleTodos selector with multiple visibleTodoList container instances will not memoize correctly

const mapStateToProps = (state, props) => {
  return {
     // WARNING: THE FOLLOWING SELECTOR DOES NOT CORRECTLY MEMOIZE
     todos: getVisibleTodos(state, props)
  }
}

What does it mean? I can’t understand why this will not work.

+4
source share
1 answer

Correctly. This is because Reselect only remembers the most recent set of inputs by default:

const a = someSelector(state, 1); // first call, not memoized
const b = someSelector(state, 1); // same inputs, memoized
const c = someSelector(state, 2); // different inputs, not memoized
const d = someSelector(state, 1); // different inputs from last time, not memoized

, , - .

, mapState, ownProps, , , memoize

const mapState = (state, ownProps) => {
    const item = selectItemForThisComponent(state, ownProps.itemId);

    return {item};
}


// later
<SomeComponent itemId={1} />
<SomeComponent itemId={2} />

selectItemForThisComponent (state, 1) (state, 2) back-to-back, .

"factory", connect. mapState , connect mapState. , :

const makeUniqueSelectorInstance = () => createSelector(
    [selectItems, selectItemId],
    (items, itemId) => items[itemId]
);    


const makeMapState = (state) => {
    const selectItemForThisComponent = makeUniqueSelectorInstance();

    return function realMapState(state, ownProps) {
        const item = selectItemForThisComponent(state, ownProps.itemId);

        return {item};
    }
}

export default connect(makeMapState)(SomeComponent);

1 2 selectItemForThisComponent, , .

Redux: .

+13

Source: https://habr.com/ru/post/1691187/


All Articles