From 99976e5f64063a851ff4fb7e3a6de4aba72d1229 Mon Sep 17 00:00:00 2001 From: Deepu S Nath Date: Thu, 30 Jul 2026 23:40:35 +0530 Subject: [PATCH] Clarify why fetching stays in the Effect in "Fetching data" The "Fetching data" example keeps `page` in the Effect's dependency array while also updating it from `handleNextPageClick`, which reads as a contradiction with the page's own advice to prefer event handlers. Add a paragraph making the deciding factor explicit: fetch in the handler when a value can *only* change from that event, and synchronize in an Effect when the value can also change for other reasons (here, `page` and `query` can both come from the URL via Back/Forward). Addresses #8506 Co-Authored-By: Claude Opus 5 --- src/content/learn/you-might-not-need-an-effect.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 81a0842eb60..9bd406f68e2 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -726,6 +726,8 @@ This might seem like a contradiction with the earlier examples where you needed It doesn't matter where `page` and `query` come from. While this component is visible, you want to keep `results` [synchronized](/learn/synchronizing-with-effects) with data from the network for the current `page` and `query`. This is why it's an Effect. +This distinction matters when deciding whether to fetch inside the Effect or the event handler. If `page` could *only* ever change from `handleNextPageClick`, you could fetch directly inside that handler and drop `page` from the Effect's dependencies entirely. But `page` isn't only set by that click—like `query`, it could also come from the URL, so that Back and Forward navigation show the right results without the user touching anything. Whenever a value can change for reasons other than the event you're handling, synchronizing off of it in an Effect (rather than fetching ad hoc from every place that can change it) is what keeps `results` correct no matter which of those reasons caused the change. + However, the code above has a bug. Imagine you type `"hello"` fast. Then the `query` will change from `"h"`, to `"he"`, `"hel"`, `"hell"`, and `"hello"`. This will kick off separate fetches, but there is no guarantee about which order the responses will arrive in. For example, the `"hell"` response may arrive *after* the `"hello"` response. Since it will call `setResults()` last, you will be displaying the wrong search results. This is called a ["race condition"](https://en.wikipedia.org/wiki/Race_condition): two different requests "raced" against each other and came in a different order than you expected. **To fix the race condition, you need to [add a cleanup function](/learn/synchronizing-with-effects#fetching-data) to ignore stale responses:**