Advanced Hook Patterns — Series 3

Preview — 3 of 10 questions

A increments its counter to 3. What is B's count?

javascript
function useCounter() {
  const [count, setCount] = useState(0);
  return { count, increment: () => setCount((c) => c + 1) };
}

function A() { const { count } = useCounter(); /* ... */ }
function B() { const { count } = useCounter(); /* ... */ }
A3 — custom hooks share state by name
B0 — a custom hook is just a function that calls hooks; each call site gets its own independent useState. A and B have completely separate counters. To share state, lift it to a common parent, a Context, or an external store
Cundefined — only one component can use a hook at a time
DIt throws a "hook already in use" error

How does useDeferredValue differ from debouncing the query by 300ms?

javascript
function Results({ query }) {
  const deferredQuery = useDeferredValue(query);
  const list = useMemo(() => filterHugeList(deferredQuery), [deferredQuery]);
  return <List items={list} />;
}
AuseDeferredValue lets React render with the previous value first (keeping the UI responsive), then re-render with the new value at a lower priority — interruptible if another urgent update arrives. There is no fixed delay: on a fast machine it updates almost immediately; on a slow one it naturally lags. Debouncing always waits the full fixed time regardless of device speed
BThey are identical
CuseDeferredValue adds a guaranteed 200ms delay
DDebouncing is interruptible; useDeferredValue is not

The clock goes 0 → 1 and then sticks at 1. Why, and what is the minimal fix?

javascript
function Clock() {
  const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setSeconds(seconds + 1), 1000);
    return () => clearInterval(id);
  }, []);
  return <p>{seconds}</p>;
}
AsetInterval is unreliable; use requestAnimationFrame
BThe dependency array must include seconds, which restarts the interval every second
CThe effect runs once ([]), so the interval's callback closes over seconds from the first render, where it is 0 — forever. Every tick computes setSeconds(0 + 1) → 1. Minimal fix: use the functional updater setSeconds((s) => s + 1), which does not depend on the captured seconds
DuseState cannot be updated from inside setInterval

Sign up free to play

Answer all 10 questions (7 more), see explanations for every answer, and track your score.