javascript / intermediate
Snippet
Synchronizing Asynchronous Data Fetching with a Stale Response Flag
When fetching data in React based on dynamic props, rapid prop changes can trigger overlapping network requests that resolve out of order (race conditions). By maintaining a boolean flag (`isCurrent`) scoped to each effect lifecycle and toggling it to `false` in the cleanup function, you ensure that stale asynchronous responses or errors are discarded if the component re-renders with a new `userId` before the previous promise resolves.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function UserProfile({ userId }) {const [userData, setUserData] = React.useState(null);const [fetchError, setFetchError] = React.useState(null);React.useEffect(() => {let isCurrent = true;async function loadUser() {try {const response = await fetch(`/api/users/${userId}`);if (!response.ok) throw new Error(`HTTP status: ${response.status}`);const data = await response.json();if (isCurrent) {setUserData(data);}} catch (err) {if (isCurrent) {setFetchError(err.message);}}}loadUser();return () => {isCurrent = false;};}, [userId]);return <div>{fetchError ? `Error: ${fetchError}` : userData?.name}</div>;}
react
Breakdown
1
let isCurrent = true;
Initializes a closure flag for the current effect cycle to track whether the active fetch request is still relevant.
2
if (isCurrent) { setUserData(data); }
Applies the received payload to state only if the effect execution context has not been superseded by a newer render.
3
return () => { isCurrent = false; };
Executes during cleanup when the component unmounts or before re-running the effect, marking pending responses as obsolete.