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 immutablecreateSelector
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
orprop
as its argument
const mapStateToProps = state => {
return {
todos: getVisibleTodos(state)
}
}
const mapStateToProps = (state, props) => {
return {
todos: getVisibleTodos(state, props)
}
}