Porozumění renderování
React se dá shrnout do jedné rovnice: vaše UI je čistá funkce vašeho stavu. Přesto je otázka „kdy přesně React renderuje?“ jednou z nejčastějších příčin zmatku – i u zkušených vývojářů.
- •Co přesně znamená „renderování“ v Reactu
- •Kdy React renderuje a re-renderuje komponenty
- •Jak fungují snapshoty props, state a event handlerů
- •Kdy React re-render přeskočí
- •Jak funguje batchování aktualizací a proč na něm záleží
- •Proč se znovu renderují i podkomponenty a jak to řídit
Mentální model Reactu můžeme zhuštit do jediné rovnice:
v = f(s)Vaše UI (v) je výsledkem volání funkce (f) s komponentním stavem (s). To ale vyvolává důležitou otázku: kdy přesně React volá tuto funkci?
Co vlastně znamená renderování
Renderování je proces, při kterém React zavolá vaši komponentní funkci, aby vytvořil popis UI.
- •React vezme snapshot vaší komponenty v určitém čase
- •Tento snapshot obsahuje props, state, event handlery a JSX
- •React použije JSX výstup k aktualizaci skutečného DOMu
import { createRoot } from "react-dom/client"
import Dashboard from "./Dashboard"
const el = document.getElementById("root")
const root = createRoot(el)
root.render(<Dashboard />)Kdy React re-renderuje?
React re-renderuje komponentu pouze tehdy, když se změní její state.
Když se změní state rodičovské komponenty, React re-renderuje rodiče — a poté ve výchozím nastavení všechny jeho potomky.
function Spark() {
console.log("Spark rendered")
return <span>✨</span>
}
export default function Header() {
const [count, setCount] = React.useState(0)
return (
<h1>
Greetings <Spark />{" "}
<button onClick={() => setCount(c => c + 1)}>Update</button>
</h1>
)
}Snapshoty a event handlery
Když se spustí event handler, vidí props a state ze snapshotu renderu, ve kterém byl vytvořen.
export default function Lamp() {
const [mode, setMode] = React.useState("off")
function toggle() {
setMode("on")
console.log("Current mode inside handler:", mode)
}
return <button onClick={toggle}>{mode}</button>
}Při prvním kliknutí snapshot říká mode = "off", takže konzole vypíše "off", i když voláte setMode("on"). Při dalším renderu se snapshot aktualizuje.
Kdy React re-render přeskočí
Pokud nastavíte state na úplně stejnou hodnotu jako předtím, React pro danou komponentu re-render přeskočí.
export default function Counter() {
const [n, setN] = React.useState(5)
function reset() {
setN(5) // same as existing state
}
return <button onClick={reset}>{n}</button>
}Jak React batchuje aktualizace state
Uvnitř jednoho event handleru React batchuje aktualizace state a aplikuje je dohromady až po dokončení handleru.
function handle() {
setLevel(10)
setLevel(20)
setLevel(30)
}Konečná hodnota bude 30, ne 10 → 20 → 30. S funkcionálními aktualizacemi může každá aktualizace vidět nejnovější mezihodnotu:
function handle() {
setLevel(1) // Intermediate: 1
setLevel(l => l + 4) // Intermediate: 5
setLevel(100) // Overwrites: 100
setLevel(l => l + 6) // Final: 106
}StrictMode a dvojité renderování
V režimu vývoje Reactův StrictMode záměrně renderuje komponenty dvakrát, aby odhalil nečistou logiku a nebezpečné vedlejší efekty.
import { StrictMode } from "react"
root.render(
<StrictMode>
<Dashboard />
</StrictMode>
)Toto chování se děje pouze v režimu vývoje a v produkčních buildch zmizí.
Shrnutí
- •React re-renderuje, když se změní state
- •Event handlery vždy vidí snapshot z renderu, ve kterém byly definovány
- •React batchuje aktualizace state a aplikuje je najednou
- •Rodiče se re-renderují → děti se re-renderují, pokud nepoužijete memoizaci
- •StrictMode provádí dvojité renderování pouze v režimu vývoje
S tímto mentálním modelem se většina otázek ohledně renderování v Reactu stává předvídatelnou — i ve velkých aplikacích.