A search component shows results for whatever the user types. Each keystroke triggers a lookup and displays "Results for: [query]". The result is always one step behind — it shows what was typed before the current keystroke, not the current value.
Type "a" — result shows "Results for: " (empty). Type "b" — result shows "Results for: a". Every result lags one keystroke behind. The display never catches up to what is currently in the input.
The callback runs after handleChange returns — which variable still holds the value you typed?
The callback runs after handleChange returns — which variable still holds the value you typed?
Why this fixes it
The setTimeout callback closed over query from the render in which handleChange was called — but setQuery(val) does not update query synchronously, so by the time the callback ran, query still held the previous render's value, producing a result that was always one keystroke behind. Replacing query inside the callback with val — the local variable captured from e.target.value before the timeout was scheduled — gives the closure a value that is already correct and does not depend on state having flushed. Because val is a plain local variable scoped to that specific invocation of handleChange, it never goes stale.