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 useEffect over useLayoutEffect by default
useLayoutEffect can block paint; reserve it for layout measurement that must run before paint.
Bad example
| 1 | import { useLayoutEffect, useState } from "react"; |
| 2 |
|
| 3 | export function StickyHeader() { |
| 4 | const [isCompact, setIsCompact] = useState(false); |
| 5 |
|
| 6 | useLayoutEffect(function onScrollLayout() { |
| 7 | const onScroll = () => { |
| 8 | setIsCompact(window.scrollY > 40); |
| 9 | }; |
| 10 |
|
| 11 | window.addEventListener("scroll", onScroll); |
| 12 | onScroll(); |
| 13 |
|
| 14 | return () => { |
| 15 | window.removeEventListener("scroll", onScroll); |
| 16 | }; |
| 17 | }, []); |
| 18 |
|
| 19 | return <header className={isCompact ? "compact" : ""}>Header</header>; |
| 20 | } |
Explanation (EN)
Synchronous layout effects delay paint even when their work has no pre-paint requirement.
Objašnjenje (HR)
Sinkroni layout effect odgađa paint i kada njegov posao ne mora završiti prije prikaza.
Good example
| 1 | import { useEffect, useState } from "react"; |
| 2 |
|
| 3 | export function StickyHeader() { |
| 4 | const [isCompact, setIsCompact] = useState(false); |
| 5 |
|
| 6 | useEffect(function onScroll() { |
| 7 | const onScroll = () => { |
| 8 | setIsCompact(window.scrollY > 40); |
| 9 | }; |
| 10 |
|
| 11 | window.addEventListener("scroll", onScroll, { passive: true }); |
| 12 | onScroll(); |
| 13 |
|
| 14 | return () => { |
| 15 | window.removeEventListener("scroll", onScroll); |
| 16 | }; |
| 17 | }, []); |
| 18 |
|
| 19 | return <header className={isCompact ? "compact" : ""}>Header</header>; |
| 20 | } |
Explanation (EN)
useEffect schedules work after paint, reducing the risk of blocking rendering. UseLayoutEffect should be reserved for DOM measurements that must be synchronous.
Objašnjenje (HR)
useEffect radi nakon painta i smanjuje rizik blokiranja rendera. useLayoutEffect ostavi za DOM mjerenja koja moraju biti sinkrona.
Notes (EN)
Use the nonblocking effect phase unless the initial measurement or synchronous DOM update must complete before paint.
Bilješke (HR)
Koristi effect koji ne blokira paint osim kada početno mjerenje ili sinkrona promjena DOM-a mora završiti prije prikaza.
Exceptions / Tradeoffs (EN)
A scroll-restored header may need pre-paint initialization to avoid a visible jump; assess that contract before moving its initial read into useEffect.
Iznimke / Tradeoffi (HR)
Header pri obnovljenom scroll položaju može trebati inicijalizaciju prije painta kako ne bi poskočio. Provjeri taj zahtjev prije premještanja početnog čitanja u useEffect.