Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Guard against stale async responses
Only commit async results if they belong to the latest request identity.
Bad example
| 1 | import { useEffect, useState } from "react"; |
| 2 |
|
| 3 | export function Profile({ userId }: { userId: string }) { |
| 4 | const [profile, setProfile] = useState<any>(null); |
| 5 |
|
| 6 | useEffect(function loadProfile() { |
| 7 | fetch(`/api/profile/${userId}`) |
| 8 | .then((r) => r.json()) |
| 9 | .then(setProfile); |
| 10 | }, [userId]); |
| 11 |
|
| 12 | return <pre>{JSON.stringify(profile, null, 2)}</pre>; |
| 13 | } |
Explanation (EN)
If userId changes quickly (navigation), an older request can resolve last and overwrite the newer profile. The UI shows the wrong user data.
Objašnjenje (HR)
Ako se userId brzo mijenja (navigacija), stariji request se moze zadnji vratiti i prepisati noviji profil. UI prikaze krive podatke.
Good example
| 1 | import { useEffect, useRef, useState } from "react"; |
| 2 |
|
| 3 | type Profile = { id: string; name: string }; |
| 4 |
|
| 5 | export function Profile({ userId }: { userId: string }) { |
| 6 | const [profile, setProfile] = useState<Profile | null>(null); |
| 7 | const latestKeyRef = useRef<string>(""); |
| 8 |
|
| 9 | useEffect(function loadProfile() { |
| 10 | const key = userId; |
| 11 | latestKeyRef.current = key; |
| 12 |
|
| 13 | fetch(`/api/profile/${userId}`) |
| 14 | .then((r) => r.json() as Promise<Profile>) |
| 15 | .then((data) => { |
| 16 | if (latestKeyRef.current !== key) return; |
| 17 | setProfile(data); |
| 18 | }); |
| 19 | }, [userId]); |
| 20 |
|
| 21 | return <pre>{JSON.stringify(profile, null, 2)}</pre>; |
| 22 | } |
Explanation (EN)
A ref stores the latest request key. Results are applied only if the response still matches the current key, preventing stale overwrites.
Objašnjenje (HR)
Ref cuva zadnji request key. Rezultat se primjenjuje samo ako response i dalje odgovara trenutnom keyu, sto sprjecava stale prepisivanje.
Notes (EN)
Prefer AbortController when possible. Use identity guards when abort isn't available or when multiple async sources can resolve out of order.
Bilješke (HR)
Preferiraj AbortController kad god mozes. Koristi identity guard kad abort nije dostupan ili kad vise async izvora moze doci van redoslijeda.