MediumHook Patterns🐛 Debug Challenge

useMemo returns cached value but deps comparison is wrong

Buggy Code — Can you spot the issue?

let computeCount = 0;

function useMemo(factory, deps) {
  let cached = null;
  return function get(newDeps) {
    // Bug: comparing arrays by reference — always different!
    if (cached && cached.deps === newDeps) {
      return cached.value;
    }
    computeCount++;
    cached = { value: factory(), deps: newDeps };
    return cached.value;
  };
}

const getValue = useMemo(() => computeCount * 100, []);

getValue([1, 2]);
getValue([1, 2]);
getValue([1, 2]);

console.log(computeCount); // should be 1, is 3

Fixed Code

let computeCount = 0;

function useMemo(factory, deps) {
  let cached = null;
  return function get(newDeps) {
    const isSame = cached &&
      cached.deps.length === newDeps.length &&
      cached.deps.every((d, i) => d === newDeps[i]); // element-by-element
    if (isSame) {
      return cached.value;
    }
    computeCount++;
    cached = { value: factory(), deps: newDeps };
    return cached.value;
  };
}

const getValue = useMemo(() => computeCount * 100, []);

getValue([1, 2]);
getValue([1, 2]);
getValue([1, 2]);

console.log(computeCount);

Bug Explained

Bug: cached.deps === newDeps compares array references. [1,2] === [1,2] is false (different objects). Cache never hits, recomputes every call.

Explanation: Element-by-element comparison: same length and all elements ===. New [1,2] arrays have the same content, so cache hits on the 2nd and 3rd calls.

Key Insight: React compares deps shallowly — each element with ===, not the array reference. Two different [1,2] arrays are considered 'same deps'. This is why primitive deps work but object deps don't.

Practice spotting bugs live →

38 debug challenges with AI hints

🐛 Try Debug Lab