If we want to memoize selectors, and the selector only depends on the state (not props), we can declare the selector outside of the component, as follows:
- Edit the src/components/TodoList.js file, and import the createSelector function from reselect:
import { createSelector } from 'reselect'
- Then, we define selectors for the todos and filter parts of the state, before the component definition:
const todosSelector = state => state.todos
const filterSelector = state => state.filter
If selectors are used by many components, it might make sense to put them in a separate selectors.js file, and import them from there. For example, we could put the filterSelector in a separate file, and then import it in TodoList.js, as well as TodoFilter.js.
- Now, we define a selector for the filtered todos, before the component is defined, as follows:
const selectFilteredTodos = createSelector(
- First, we specify the other two selectors that we want to reuse:
todosSelector,
filterSelector,
- Now, we specify a filtering selector, copying the code from the useMemo Hook:
(todos, filter) => {
switch (filter) {
case 'active':
return todos.filter(t => t.completed === false)
case 'completed':
return todos.filter(t => t.completed === true)
default:
case 'all':
return todos
}
}
)
- Finally, we use our defined selector in the Selector Hook:
export default function TodoList () {
const filteredTodos = useSelector(selectFilteredTodos)
Now that we have defined a reusable selector for the filtered todos, the result of filtering the todos will be memoized, and will not be re-computed if the state did not change.