1 min lesson
Effect pitfalls
Use the example in "Effect pitfalls" to explain the main idea in plain words.
Step 1 of 2
Effect pitfallswhere async bites
Effects are where most bugs live in an interview. The dependency array must list every reactive value the effect reads, async effects need a cancellation guard and anything you subscribe to you must clean up.
useEffect(() => {
let cancelled = false;
fetchPreview(query).then((data) => {
if (!cancelled) setPreview(data); // ignore the late response
});
return () => { cancelled = true; }; // runs before the next effect / on unmount
}, [query]);Narrate renders as you go: “this sets state, so this subtree re-renders; I'm memoizing the row callback because the list is virtualized and identity churn would re-render every row.” Cursor probes the why and a clean spoken model of renders is the signal they want.
Reaching for useEffect to derive render data is the most common tell. If a value can be computed during render from props and state, compute it there - an effect that just calls setState from other state creates an extra render and a class of stale-value bugs.