Rules Hub
Code Ruleset
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Prefer AbortController over manual flags for effect cleanup
Use AbortController for abortable effect work, retaining a final stale-result guard when cancellation cannot cover every async stage.
Bad example
| 1 | useEffect(() => { |
| 2 | let isActive = true; |
| 3 | const controller = new AbortController(); |
| 4 |
|
| 5 | fetch('/api/data', { signal: controller.signal }) |
| 6 | .then((res) => res.json()) |
| 7 | .then((data) => { |
| 8 | if (isActive) { |
| 9 | setData(data); |
| 10 | } |
| 11 | }); |
| 12 |
|
| 13 | return () => { |
| 14 | isActive = false; |
| 15 | controller.abort(); |
| 16 | }; |
| 17 | }, []); |
Explanation (EN)
A manual flag alone does not cancel I/O, but removing every commit guard can reintroduce stale updates.
Objašnjenje (HR)
Sama zastavica ne prekida I/O, ali uklanjanje svake zaštite zapisa može vratiti zastarjele promjene stanja.
Good example
| 1 | useEffect(() => { |
| 2 | const controller = new AbortController(); |
| 3 | fetch(url, { signal: controller.signal }) |
| 4 | .then(response => response.json()) |
| 5 | .then(data => { if (!controller.signal.aborted) setData(data); }) |
| 6 | .catch(error => { |
| 7 | if (error === controller.signal.reason) return; |
| 8 | reportError(error); |
| 9 | }); |
| 10 | return () => controller.abort(); |
| 11 | }, [url]); |
Explanation (EN)
The controller cancels supported work and the final guard also covers completion that raced with cleanup.
Objašnjenje (HR)
Controller prekida podržani posao, a završna provjera pokriva i rezultat koji se završio istodobno s cleanupom.
Notes (EN)
Prefer actual cancellation for work that supports AbortSignal; before removing a lifecycle flag, inspect every later async stage and the final state commit.
Exceptions / Tradeoffs (EN)
If AbortController isn't available in the target runtime, a simple mounted flag can be acceptable. For complex multi-step cancellations, a higher-level abstraction may be clearer. Cancellation cannot undo an already resolved promise or non-abortable transform. Keep a final signal/sequence guard or an independent lifecycle flag when those paths can finish after teardown.
Iznimke / Tradeoffi (HR)
Ako AbortController nije dostupan ili posao nije prekidiv, zastavica životnog ciklusa može biti opravdana. Složen posao može trebati višu apstrakciju. Otkazivanje ne poništava već razriješen promise ni neprekidivu transformaciju; zadrži završnu provjeru signala, rednog broja ili aktivnog životnog ciklusa.