Exercise 3: Why the Debounce Cleanup Line Matters — Possible Solution ==================================================================== WHAT HAPPENS IF THE CLEANUP FUNCTION IS OMITTED ------------------------------ Without return () => clearTimeout(timeoutId), every keystroke still schedules its own setTimeout call, and none of those timers are ever cancelled. Typing five characters quickly would schedule five separate timers, every one of which eventually fires and triggers its own fetch request - the delay pushes when the requests happen, but does nothing to reduce how many of them ultimately fire. The whole point of debouncing - collapsing a burst of keystrokes into a single request - is defeated. WHY IT'S "THE SAME LESSON" AS CHAPTER 4's CAMERA CLEANUP ------------------------------ In both cases, useEffect re-runs its setup function every time its own dependency changes (the query string here, nothing there in Chapter 4's media-stream case except mount/unmount), and in both cases something was started in the previous run that has to be explicitly torn down before the new run starts something else - a pending timer here, an open camera stream there. The cleanup function returned from useEffect is the one place React guarantees that teardown happens before the next run, and skipping it leaves the previous run's own resource (a timer, a stream) alive and unmanaged in both cases. WHY THIS WORKS AS AN ANSWER ------------------------------ It correctly explains the concrete failure mode (timers accumulating and all eventually firing, not just one delayed request) rather than a vague "it wouldn't work right," and it correctly identifies the shared underlying principle with Chapter 4 - cleaning up what the previous effect run started - rather than treating the two chapters' cleanup functions as coincidentally similar.