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).
Prefer declarative props over imperative refs
Use refs for DOM integration only when necessary; avoid imperative APIs that bypass React data flow.
Bad example
| 1 | import { useEffect, useRef } from "react"; |
| 2 |
|
| 3 | export function AutoScrollList({ items }: { items: string[] }) { |
| 4 | const listRef = useRef<HTMLDivElement | null>(null); |
| 5 |
|
| 6 | useEffect(function forceScroll() { |
| 7 | const el = listRef.current; |
| 8 | if (!el) return; |
| 9 |
|
| 10 | // Imperative logic tightly couples behavior to DOM structure. |
| 11 | el.scrollTop = el.scrollHeight; |
| 12 | }, [items]); |
| 13 |
|
| 14 | return ( |
| 15 | <div ref={listRef} style={{ maxHeight: 200, overflow: "auto" }}> |
| 16 | {items.map((i) => ( |
| 17 | <div key={i}>{i}</div> |
| 18 | ))} |
| 19 | </div> |
| 20 | ); |
| 21 | } |
Explanation (EN)
Imperative DOM mutations inside effects can be fragile and hard to reuse. As UI changes, these assumptions break and produce subtle bugs.
Objašnjenje (HR)
Imperativne DOM mutacije u efektima mogu biti krhke i teske za reuse. Kako se UI mijenja, pretpostavke pucaju i nastaju suptilni bugovi.
Good example
| 1 | import { useEffect, useRef } from "react"; |
| 2 |
|
| 3 | export function AutoScrollList({ items }: { items: string[] }) { |
| 4 | const listRef = useRef<HTMLDivElement | null>(null); |
| 5 |
|
| 6 | useEffect(function scrollToBottom() { |
| 7 | const el = listRef.current; |
| 8 | if (!el) return; |
| 9 |
|
| 10 | el.scrollTo({ top: el.scrollHeight, behavior: "smooth" }); |
| 11 | }, [items.length]); |
| 12 |
|
| 13 | return ( |
| 14 | <div ref={listRef} style={{ maxHeight: 200, overflow: "auto" }}> |
| 15 | {items.map((i) => ( |
| 16 | <div key={i}>{i}</div> |
| 17 | ))} |
| 18 | </div> |
| 19 | ); |
| 20 | } |
Explanation (EN)
If refs are needed, keep the imperative surface minimal and tied to a clear UI requirement. Prefer dependency primitives (like items.length) to reduce unnecessary runs.
Objašnjenje (HR)
Ako su refovi potrebni, drzi imperativnu povrsinu minimalnom i vezanom uz jasan UI zahtjev. Preferiraj primitivne ovisnosti (poput items.length) da smanjis nepotrebna pokretanja.
Notes (EN)
For reusable imperative APIs (focus/scroll), consider exposing a small `useImperativeHandle` surface from a dedicated component instead of mutating many DOM nodes from outside.
Bilješke (HR)
Za reusable imperativne API-je (focus/scroll), razmisli o malom `useImperativeHandle` sucelju iz dedicated komponente umjesto mutiranja vise DOM cvorova izvana.
Exceptions / Tradeoffs (EN)
Refs are appropriate for focus management, measuring layout, integrating non-React libraries, and escape hatches where declarative patterns are not possible.
Iznimke / Tradeoffi (HR)
Refovi su opravdani za focus management, mjerenje layouta, integraciju non-React libraryja i escape hatch situacije gdje deklarativni pristup nije moguc.