Memoized selector
Implement createSelector(inputs, compute). inputs is an array of functions of the state. The selector calls every input with the state. When every input result is the same as last time (compared with ===), it returns the previous output without calling compute. Otherwise it calls compute with the input results and remembers the output. In the tests the inputs read state.todos and state.filter. s1 is the base state; s2 changes an unrelated field; s3 changes the filter; s4 has a new todos array with the same items. The answer shows how often compute ran and whether each output was the same reference as the one before.
Start from
function createSelector(inputs, compute) {
// Return a selector that recomputes only when an input result changed.
}Hints
Each hint gives away a little more. Open one only when you need it.
Hint 1
Remember the last input results and the last output in the closure.
Hint 2
Compare the new input results with the old ones, one by one, with ===. A cache of one entry is enough.
Solution
From here on the page gives the method away. If you are still solving, go back to the hints.
JavaScript
function createSelector(inputs, compute) {
let lastArgs = null;
let lastResult;
return (state) => {
const args = inputs.map((input) => input(state));
if (lastArgs && args.every((arg, index) => arg === lastArgs[index]))
return lastResult;
lastArgs = args;
lastResult = compute(...args);
return lastResult;
};
}What an interviewer looks for
This is reselect in ten lines. It shows why selectors return stable references, and why a new array from filter on every render causes extra renders.