Hint
useMemo prevents expensive recomputation when inputs haven't changed. The result reference is also stable — good for passing to React.memo children as props.
let computeCount = 0;
function useMemo(factory, deps) {
let cached = null;
return function get(newDeps) {
if (cached && newDeps.every((d, i) => d === cached.deps[i])) {
return cached.value;
}
computeCount++;
cached = { value: factory(...newDeps), deps: newDeps };
return cached.value;
};
}
const getFiltered = useMemo(
(items, query) => items.filter(x => x.includes(query)),
[]
);
const items = ['apple', 'banana', 'apricot'];
const r1 = getFiltered([items, 'ap']);
const r2 = getFiltered([items, 'ap']); // same deps
const r3 = getFiltered([items, 'ban']); // query changed
console.log(computeCount);
console.log(r1.join(','));
console.log(r2.join(','));
console.log(r3.join(','));2 apple,apricot apple,apricot banana
Explanation: computeCount=2 (initial + when query changed to 'ban'). r1 and r2 are the same computation. r3 recomputes with new query.
Key Insight: useMemo prevents expensive recomputation when inputs haven't changed. The result reference is also stable — good for passing to React.memo children as props.