Redux Memoized Selectors - Tuong-Nguyen/JavaScript-Structure GitHub Wiki

Use Case

When the data is calculated every time the component is updated, if the state tree is large or the calculation is expensive, repeating the calculation on every update may cause performance problems.

Solution

  • Use Reselect library for creating memoized, composable selector function.
  • The selector will call the transform function with the values of input-selectors as arguments and return the result
    • If the values of input-selectors are the same as previous call to selector, it will return the previously computed value instead of calling the transform function.
  • Selectors are shallow compared

Creating a Memoized Selector

  • Create memoized selector by using createSelector function
  • createSelector's arguments are immutable
  • createSelector take 2 arguments
    • Array of input-selectors
    • Transform function
// Input-Selectors
const getVisibilityFilter = state => state.visibilityFilter;
const getTodos = state => state.todos;

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

Composing Selectors

  • A memoized selector can be an input-selector of another one.
const getKeyword = state => state.keyword

const getVisibleTodosFilteredByKeyword = createSelector(
  [getVisibleTodos, getKeyword],
  (visibleTodos, keyword) =>
    visibleTodos.filter(todo => todo.text.indexOf(keyword) > -1)
)

Connect Selector to Redux Store

  • Call selectors inside mapStateToProps()
  • Memoized selectors can take state or prop as its argument
const mapStateToProps = state => {
  return {
    todos: getVisibleTodos(state)
  }
}
const mapStateToProps = (state, props) => {
  return {
    todos: getVisibleTodos(state, props)
  }
}

Sharing Selectors across multiple components

http://redux.js.org/docs/recipes/ComputingDerivedData.html#sharing-selectors-across-multiple-components