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).
Avoid stale closures in long-lived callbacks
Timers and event listeners should not read stale state; use refs or explicit dependencies.
Bad example
| 1 | import { useEffect, useState } from "react"; |
| 2 |
|
| 3 | export function Counter() { |
| 4 | const [count, setCount] = useState(0); |
| 5 |
|
| 6 | useEffect(function tick() { |
| 7 | const id = window.setInterval(() => { |
| 8 | // Captures `count` from the first render => stale. |
| 9 | setCount(count + 1); |
| 10 | }, 1000); |
| 11 |
|
| 12 | return () => window.clearInterval(id); |
| 13 | }, []); |
| 14 |
|
| 15 | return <div>{count}</div>; |
| 16 | } |
Explanation (EN)
The interval callback captures the initial `count` value. The counter can get stuck or behave unexpectedly because the closure is stale.
Objašnjenje (HR)
Interval callback hvata pocetnu vrijednost `count`. Brojac moze zapeti ili se cudno ponasati jer je closure stale.
Good example
| 1 | import { useEffect, useState } from "react"; |
| 2 |
|
| 3 | export function Counter() { |
| 4 | const [count, setCount] = useState(0); |
| 5 |
|
| 6 | useEffect(function tick() { |
| 7 | const id = window.setInterval(() => { |
| 8 | setCount((c) => c + 1); |
| 9 | }, 1000); |
| 10 |
|
| 11 | return () => window.clearInterval(id); |
| 12 | }, []); |
| 13 |
|
| 14 | return <div>{count}</div>; |
| 15 | } |
Explanation (EN)
Using a functional state update avoids reading `count` from a stale closure. For more complex cases, store latest values in refs.
Objašnjenje (HR)
Funkcionalni update stanja izbjegava citanje `count` iz stale closura. Za kompleksnije slucajeve, cuvaj latest vrijednosti u refovima.
Notes (EN)
For event listeners reading changing values, combine a stable handler with a ref that stores the latest value.
Bilješke (HR)
Za event listenere koji citaju promjenjive vrijednosti, kombiniraj stabilan handler s refom koji cuva latest vrijednost.
Exceptions / Tradeoffs (EN)
If you intentionally want a value frozen at subscription time, document the intent so readers don't 'fix' it incorrectly.
Iznimke / Tradeoffi (HR)
Ako namjerno zelis zamrznuti vrijednost u trenutku subscribea, dokumentiraj namjeru da netko ne 'popravi' pogresno.