> For the complete documentation index, see [llms.txt](https://bryan-guner.gitbook.io/my-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bryan-guner.gitbook.io/my-docs/redux/docs-13/md-docs/computing-derived-data.md).

# computing-derived-data

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

[Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html)[Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-1-overview-concepts.html)[API](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/api-reference.html)[FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq.html)[Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/style-guide/style-guide.html)[GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/github.com/reduxjs/redux.html)[Need help?](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html#help-and-discussion)

🌜

🌞

Search

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

* [Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html)
* [Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-1-overview-concepts.html)
* [API](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/api-reference.html)
* [FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq.html)
* [Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/style-guide/style-guide.html)
* [GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/github.com/reduxjs/redux.html)
* [Need help?](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html#help-and-discussion)
* [Introduction](#!)
  * [Getting Started with Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html)
  * [Installation](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/installation.html)
  * [Core Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/core-concepts.html)
  * [Learning Resources](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/learning-resources.html)
  * [Ecosystem](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/ecosystem.html)
  * [Examples](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/examples.html)
* [Tutorials](#!)
  * [Tutorials Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/index.html)
  * [Quick Start](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/quick-start.html)
  * [TypeScript Quick Start](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/typescript-quick-start.html)
  * [Redux Essentials](#!)
    * [Redux Overview and Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-1-overview-concepts.html)
    * [Redux App Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-2-app-structure.html)
    * [Basic Redux Data Flow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-3-data-flow.html)
    * [Using Redux Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-4-using-data.html)
    * [Async Logic and Data Fetching](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-5-async-logic.html)
    * [Performance and Normalizing Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-6-performance-normalization.html)
  * [Redux Fundamentals](#!)
    * [Redux Overview](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-1-overview.html)
    * [Redux Concepts and Data Flow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-2-concepts-data-flow.html)
    * [State, Actions, and Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-3-state-actions-reducers.html)
    * [Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-4-store.html)
    * [UI and React](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-5-ui-react.html)
    * [Async Logic and Data Fetching](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-6-async-logic.html)
    * [Standard Redux Patterns](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-7-standard-patterns.html)
    * [Modern Redux with Redux Toolkit](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-8-modern-redux.html)
* [Recipes](#!)
  * [Recipes: Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/recipe-index.html)
  * [Configuring Your Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/configuring-your-store.html)
  * [Usage With TypeScript](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/usage-with-typescript.html)
  * [Migrating to Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/migrating-to-redux.html)
  * [Using Object Spread Operator](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/using-object-spread-operator.html)
  * [Reducing Boilerplate](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/reducing-boilerplate.html)
  * [Server Rendering](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/server-rendering.html)
  * [Writing Tests](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/writing-tests.html)
  * [Computing Derived Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/computing-derived-data.html)
  * [Implementing Undo History](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/implementing-undo-history.html)
  * [Isolating Redux Sub-Apps](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/isolating-redux-sub-apps.html)
  * [Code Splitting](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/code-splitting.html)
  * [Troubleshooting](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/troubleshooting.html)
  * [Structuring Reducers](#!)
    * [Structuring Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/structuring-reducers.html)
    * [Prerequisite Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/prerequisite-concepts.html)
    * [Basic Reducer Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/basic-reducer-structure.html)
    * [Splitting Reducer Logic](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/splitting-reducer-logic.html)
    * [Refactoring Reducers Example](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/refactoring-reducer-example.html)
    * [Using combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/using-combinereducers.html)
    * [Beyond combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/beyond-combinereducers.html)
    * [Normalizing State Shape](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/normalizing-state-shape.html)
    * [Updating Normalized Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/updating-normalized-data.html)
    * [Reusing Reducer Logic](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/reusing-reducer-logic.html)
    * [Immutable Update Patterns](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/immutable-update-patterns.html)
    * [Initializing State](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers/initializing-state.html)
* [Understanding Redux](#!)
  * [Thinking in Redux](#!)
    * [Motivation](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/understanding/thinking-in-redux/motivation.html)
    * [Three Principles](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/understanding/thinking-in-redux/three-principles.html)
    * [Glossary](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/understanding/thinking-in-redux/glossary.html)
  * [History and Design](#!)
    * [Prior Art](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/understanding/history-and-design/prior-art.html)
    * [Middleware](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/understanding/history-and-design/middleware.html)
* [FAQ](#!)
  * [FAQ Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq.html)
  * [General](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/general.html)
  * [Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/reducers.html)
  * [Organizing State](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/organizing-state.html)
  * [Store Setup](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/store-setup.html)
  * [Actions](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/actions.html)
  * [Immutable Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/immutable-data.html)
  * [Code Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/code-structure.html)
  * [Performance](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/performance.html)
  * [Design Decisions](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/design-decisions.html)
  * [React Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/react-redux.html)
  * [Miscellaneous](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq/miscellaneous.html)
* [Style Guide](#!)
  * [Style Guide: Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/style-guide/style-guide.html)
* [API Reference](#!)
  * [API Reference](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/api-reference.html)
  * [createStore](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/createstore.html)
  * [Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/store.html)
  * [combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/combinereducers.html)
  * [applyMiddleware](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/applymiddleware.html)
  * [bindActionCreators](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/bindactioncreators.html)
  * [compose](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/compose.html)
* [Redux Toolkit](#!)
  * [Redux Toolkit: Overview](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/redux-toolkit/overview.html)

## Computing Derived Data[#](#computing-derived-data)

[Reselect](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/reselect.html) is a simple library for creating memoized, composable **selector** functions. Reselect selectors can be used to efficiently compute derived data from the Redux store.

#### Motivation for Memoized Selectors[#](#motivation-for-memoized-selectors)

Let's revisit the [Todos List example](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/fundamentals/part-5-ui-react.html):

**`containers/VisibleTodoList.js`**[**#**](#containersvisibletodolistjs)

import { connect } from 'react-redux'

import { toggleTodo } from '../actions'

import TodoList from '../components/TodoList'

const getVisibleTodos = (todos, filter) => {

switch (filter) {

case 'SHOW\_ALL':

return todos

case 'SHOW\_COMPLETED':

return todos.filter(t => t.completed)

case 'SHOW\_ACTIVE':

return todos.filter(t => !t.completed)

}

}

const mapStateToProps = state => {

return {

todos: getVisibleTodos(state.todos, state.visibilityFilter)

}

}

const mapDispatchToProps = dispatch => {

return {

onTodoClick: id => {

dispatch(toggleTodo(id))

}

}

}

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList)

export default VisibleTodoList

Copy

In the above example, `mapStateToProps` calls `getVisibleTodos` to calculate `todos`. This works great, but there is a drawback: `todos` is calculated every time the component is updated. If the state tree is large, or the calculation expensive, repeating the calculation on every update may cause performance problems. Reselect can help to avoid these unnecessary recalculations.

#### Creating a Memoized Selector[#](#creating-a-memoized-selector)

We would like to replace `getVisibleTodos` with a memoized selector that recalculates `todos` when the value of `state.todos` or `state.visibilityFilter` changes, but not when changes occur in other (unrelated) parts of the state tree.

Reselect provides a function `createSelector` for creating memoized selectors. `createSelector` takes an array of input-selectors and a transform function as its arguments. If the Redux state tree is changed in a way that causes the value of an input-selector to change, the selector will call its transform function with the values of the input-selectors as arguments and return the result. If the values of the input-selectors are the same as the previous call to the selector, it will return the previously computed value instead of calling the transform function.

Let's define a memoized selector named `getVisibleTodos` to replace the non-memoized version above:

**`selectors/index.js`**[**#**](#selectorsindexjs)

import { createSelector } from 'reselect'

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)

}

}

)

Copy

In the example above, `getVisibilityFilter` and `getTodos` are input-selectors. They are created as ordinary non-memoized selector functions because they do not transform the data they select. `getVisibleTodos` on the other hand is a memoized selector. It takes `getVisibilityFilter` and `getTodos` as input-selectors, and a transform function that calculates the filtered todos list.

#### Composing Selectors[#](#composing-selectors)

A memoized selector can itself be an input-selector to another memoized selector. Here is `getVisibleTodos` being used as an input-selector to a selector that further filters the todos by keyword:

const getKeyword = state => state.keyword

const getVisibleTodosFilteredByKeyword = createSelector(

\[getVisibleTodos, getKeyword],

(visibleTodos, keyword) =>

visibleTodos.filter(todo => todo.text.indexOf(keyword) > -1)

)

Copy

#### Connecting a Selector to the Redux Store[#](#connecting-a-selector-to-the-redux-store)

If you are using [React Redux](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/react-redux.html), you can call selectors as regular functions inside `mapStateToProps()`:

**`containers/VisibleTodoList.js`**[**#**](#containersvisibletodolistjs-1)

import { connect } from 'react-redux'

import { toggleTodo } from '../actions'

import TodoList from '../components/TodoList'

import { getVisibleTodos } from '../selectors'

const mapStateToProps = state => {

return {

todos: getVisibleTodos(state)

}

}

const mapDispatchToProps = dispatch => {

return {

onTodoClick: id => {

dispatch(toggleTodo(id))

}

}

}

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList)

export default VisibleTodoList

Copy

#### Accessing React Props in Selectors[#](#accessing-react-props-in-selectors)

So far we have only seen selectors receive the Redux store state as an argument, but a selector can receive props too.

For this example, we're going to extend our app to handle multiple Todo lists. Our state needs to be refactored so that it holds multiple todo lists, which each have their own `todos` and `visibilityFilter` state.

We also need to refactor our reducers. Now that `todos` and `visibilityFilter` live within every list's state, we only need one `todoLists` reducer to manage our state.

**`reducers/index.js`**[**#**](#reducersindexjs)

import { combineReducers } from 'redux'

import todoLists from './todoLists'

export default combineReducers({

todoLists

})

Copy

**`reducers/todoLists.js`**[**#**](#reducerstodolistsjs)

// Note that we're hard coding three lists here just as an example.

// In the real world, we'd have a feature to add/remove lists,

// and this would be empty initially.

const initialState = {

1: {

todos: \[],

visibilityFilter: 'SHOW\_ALL'

},

2: {

todos: \[],

visibilityFilter: 'SHOW\_ALL'

},

3: {

todos: \[],

visibilityFilter: 'SHOW\_ALL'

}

}

const addTodo = (state, action) => {

const todoList = state\[action.listId]

const { todos } = todoList

return {

...state,

\[action.listId]: {

...todoList,

todos: \[

...todos,

{

id: action.id,

text: action.text,

completed: false

}

]

}

}

}

const toggleTodo = (state, action) => {

const todoList = state\[action.listId]

const { todos } = todoList

return {

...state,

\[action.listId]: {

...todoList,

todos: todos.map(todo =>

(todo.id === action.id)

? {...todo, completed: !todo.completed}

: todo

)

}

}

}

const setVisibilityFilter = (state, action) => {

const todoList = state\[action.listId]

return {

...state,

\[action.listId]: {

...todoList,

visibilityFilter: action.filter

}

}

}

export default const todoLists = (state = initialState, action) => {

// make sure a list with the given id exists

if (!state\[action.listId]) {

return state;

}

switch (action.type) {

case 'ADD\_TODO':

return addTodo(state, action)

case 'TOGGLE\_TODO':

return toggleTodo(state, action)

case 'SET\_VISIBILITY\_FILTER':

return setVisibilityFilter(state, action)

default:

return state

}

}

Copy

The `todoLists` reducer now handles all three actions. The action creators will now need to be passed a `listId`:

**`actions/index.js`**[**#**](#actionsindexjs)

let nextTodoId = 0

export const addTodo = (text, listId) => ({

type: 'ADD\_TODO',

id: nextTodoId++,

text,

listId

})

export const setVisibilityFilter = (filter, listId) => ({

type: 'SET\_VISIBILITY\_FILTER',

filter,

listId

})

export const toggleTodo = (id, listId) => ({

type: 'TOGGLE\_TODO',

id,

listId

})

export const VisibilityFilters = {

SHOW\_ALL: 'SHOW\_ALL',

SHOW\_COMPLETED: 'SHOW\_COMPLETED',

SHOW\_ACTIVE: 'SHOW\_ACTIVE'

}

Copy

**`components/TodoList.js`**[**#**](#componentstodolistjs)

import React from 'react'

import PropTypes from 'prop-types'

import Todo from './Todo'

const TodoList = ({ todos, toggleTodo, listId }) => (

\<ul>

{todos.map(todo => (

\<Todo

key={todo.id}

{...todo}

onClick={() => toggleTodo(todo.id, listId)}

/>

))}

\</ul>

)

export default TodoList

Copy

Here is an `App` component that renders three `VisibleTodoList` components, each of which has a `listId` prop:

**`components/App.js`**[**#**](#componentsappjs)

import React from 'react'

import VisibleTodoList from '../containers/VisibleTodoList'

const App = () => (

\<div>

\<VisibleTodoList listId="1" />

\<VisibleTodoList listId="2" />

\<VisibleTodoList listId="3" />

\</div>

)

Copy

Each `VisibleTodoList` container should select a different slice of the state depending on the value of the `listId` prop, so we'll modify `getVisibilityFilter` and `getTodos` to accept a props argument.

**`selectors/todoSelectors.js`**[**#**](#selectorstodoselectorsjs)

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

Copy

`props` can be passed to `getVisibleTodos` from `mapStateToProps`:

const mapStateToProps = (state, props) => {

return {

todos: getVisibleTodos(state, props)

}

}

Copy

So now `getVisibleTodos` has access to `props`, and everything seems to be working fine.

**But there is a problem!**

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

**`containers/VisibleTodoList.js`**[**#**](#containersvisibletodolistjs-2)

import { connect } from 'react-redux'

import { toggleTodo } from '../actions'

import TodoList from '../components/TodoList'

import { getVisibleTodos } from '../selectors'

const mapStateToProps = (state, props) => {

return {

// WARNING: THE FOLLOWING SELECTOR DOES NOT CORRECTLY MEMOIZE

todos: getVisibleTodos(state, props)

}

}

const mapDispatchToProps = dispatch => {

return {

onTodoClick: id => {

dispatch(toggleTodo(id))

}

}

}

const VisibleTodoList = connect(mapStateToProps, mapDispatchToProps)(TodoList)

export default VisibleTodoList

Copy

A selector created with `createSelector` only returns the cached value when its set of arguments is the same as its previous set of arguments. If we alternate between rendering `<VisibleTodoList listId="1" />` and `<VisibleTodoList listId="2" />`, the shared selector will alternate between receiving `{listId: 1}` and `{listId: 2}` as its `props` argument. This will cause the arguments to be different on each call, so the selector will always recompute instead of returning the cached value. We'll see how to overcome this limitation in the next section.

#### Sharing Selectors Across Multiple Components[#](#sharing-selectors-across-multiple-components)

> The examples in this section require React Redux v4.3.0 or greater

In order to share a selector across multiple `VisibleTodoList` components **and** retain memoization, each instance of the component needs its own private copy of the selector.

Let's create a function named `makeGetVisibleTodos` that returns a new copy of the `getVisibleTodos` selector each time it is called:

**`selectors/todoSelectors.js`**[**#**](#selectorstodoselectorsjs-1)

import { createSelector } from 'reselect'

const getVisibilityFilter = (state, props) =>

state.todoLists\[props.listId].visibilityFilter

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

const makeGetVisibleTodos = () => {

return 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 makeGetVisibleTodos

Copy

We also need a way to give each instance of a container access to its own private selector. The `mapStateToProps` argument of `connect` can help with this.

**If the `mapStateToProps` argument supplied to `connect` returns a function instead of an object, it will be used to create an individual `mapStateToProps` function for each instance of the container.**

In the example below `makeMapStateToProps` creates a new `getVisibleTodos` selector, and returns a `mapStateToProps` function that has exclusive access to the new selector:

const makeMapStateToProps = () => {

const getVisibleTodos = makeGetVisibleTodos()

const mapStateToProps = (state, props) => {

return {

todos: getVisibleTodos(state, props)

}

}

return mapStateToProps

}

Copy

If we pass `makeMapStateToProps` to `connect`, each instance of the `VisibleTodosList` container will get its own `mapStateToProps` function with a private `getVisibleTodos` selector. Memoization will now work correctly regardless of the render order of the `VisibleTodoList` containers.

**`containers/VisibleTodoList.js`**[**#**](#containersvisibletodolistjs-3)

import { connect } from 'react-redux'

import { toggleTodo } from '../actions'

import TodoList from '../components/TodoList'

import { makeGetVisibleTodos } from '../selectors'

const makeMapStateToProps = () => {

const getVisibleTodos = makeGetVisibleTodos()

const mapStateToProps = (state, props) => {

return {

todos: getVisibleTodos(state, props)

}

}

return mapStateToProps

}

const mapDispatchToProps = dispatch => {

return {

onTodoClick: id => {

dispatch(toggleTodo(id))

}

}

}

const VisibleTodoList = connect(

makeMapStateToProps,

mapDispatchToProps

)(TodoList)

export default VisibleTodoList

Copy

### Next Steps[#](#next-steps)

Check out the [official documentation](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/reselect.html) of Reselect as well as its [FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/reselect.html#faq). Most Redux projects start using Reselect when they have performance problems because of too many derived computations and wasted re-renders, so make sure you are familiar with it before you build something big. It can also be useful to study [its source code](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/reselect/blob/master/src/index.html) so you don't think it's magic.

Previous

« Writing Tests

Next

Implementing Undo History »

* [Motivation for Memoized Selectors](#motivation-for-memoized-selectors)
* [Creating a Memoized Selector](#creating-a-memoized-selector)
* [Composing Selectors](#composing-selectors)
* [Connecting a Selector to the Redux Store](#connecting-a-selector-to-the-redux-store)
* [Accessing React Props in Selectors](#accessing-react-props-in-selectors)
* [Sharing Selectors Across Multiple Components](#sharing-selectors-across-multiple-components)
* [Next Steps](#next-steps)

**Docs**

* [Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html)
* [Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/tutorials/essentials/part-1-overview-concepts.html)
* [FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/faq.html)
* [API Reference](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/api/api-reference.html)

**Community**

* [Reactiflux Discord](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/discord.com/invite/0ZcbPKXt5bZ6au5t.html)
* [Stack Overflow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/stackoverflow.com/questions/tagged/redux.html)
* [Feedback](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/introduction/getting-started.html#help-and-discussion)

**More**

* [GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/github.com/reduxjs/redux.html)
* [![Deploys by Netlify](https://github.com/bgoonz/Learning-Redux/blob/master/www.netlify.com/img/global/badges/netlify-color-accent.svg)](https://github.com/bgoonz/Learning-Redux/blob/master/www.netlify.com/index.html)

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

Copyright © 2015–2021 Dan Abramov and the Redux documentation authors.
