How does Redux Reselect memoization work?
So we have this selector getting state for our VisibleTodoList
component:
const mapStateToProps = (state, props) => {
return {
todos: getVisibleTodos(state, props)
}
}
If we render the component:
return (
<div>
<VisibleTodoList listId="1" />
</div>
)
Then, the selector gets called like: getVisibleTodos(state, { listId: 1 })
, and the selector stores (memoizes) the result (todo list 1 object) in memory.
If we render the component twice with the same props:
return (
<div>
<VisibleTodoList listId="1" />
<VisibleTodoList listId="1" />
</div>
)
the selector gets called and result gets memoized
the selector gets called a second time, and it sees that
{ listId: 1 }
is the same prop arguments as the first time, so it just returns the memoized value.
If we render the component twice with different props:
return (
<div>
<VisibleTodoList listId="1" />
<VisibleTodoList listId="2" />
</div>
)
the selector gets called and the result gets memoized
the selector gets called a second time, and it sees that
{ listId: 2 }
is not the same props args as the first time{ listId: 1 }
, so it recalculates and memoizes the new result (todo list 2 object) in memory (overwriting the previous memoization).
If we want each component to get its own memoization, each component instance must have its own selector instance.
For example:
// selector
const makeGetVisibleTodos = () => createSelector(
// ... get the visible todos
);
// each has their own memoization space:
const foo = makeGetVisibleTodos(); // this is an instance
const bar = makeGetVisibleTodos(); // this is a separate instance
So applying it to the component:
// component
const mapStateToProps = () => {
const getVisibleTodos = makeGetVisibleTodos(); // this instance get bound to the component instance
return (state, props) => {
return {
todos: getVisibleTodos(state, props)
}
}
}
Now, If we render the component twice with different props:
return (
<div>
<VisibleTodoList listId="1" />
<VisibleTodoList listId="2" />
</div>
)
with
<VisibleTodoList listId="1" />
the first instance of the selector gets called and the result gets memoizedwith
<VisibleTodoList listId="2" />
a different instance of the selector gets called and the result gets memoized