A React.js kötegelt frissítések
Már tudja, hogy amikor frissíti az összetevő állapotát, a React eltérő algoritmusa észleli a virtuális DOM változásait, és megjeleníti az összetevőt a valódi DOM -ban. De valóban ez történik minden egyes állapotfrissítésnél? Vagy a React lehetőséget biztosít a frissítések kötegelt összegyűjtésére, hogy több állapotmutáció egyetlen renderelési hívássá egyesüljön?
A szintetikus események lehetővé teszik a kötegek frissítését
A React 17 és régebbi mechanizmusok biztosítják a frissítések kötegelését. Tényleg nem kell sokat gondolkodnia a kódolás során, de annak ismerete, hogy a React hogyan optimalizálhatja a kódot, nagyszerű tanulság.
Íme, mi történik.
- visszahíváson belül több állapotmutációt hívnak meg
- ha a visszahívás szintetikus eseményhez van csatolva, a React kötegeli ezeket a mutációkat
- mutációk csoportosításakor csak egyetlen render-hívás történik
- ellenkező esetben minden mutáció új megjelenítéshez vezet
A kötegelés lehetővé tétele érdekében az állapotmutációkat egy szintetikus React-eseményen belül kell meghívni. Gyors emlékeztetőül: a szintetikus React események alapvetően csak a natív HTML-események köré épülnek, hogy minden böngészőben ugyanazt a funkciót biztosítsák. Minden szintetikus eseménykezelőt közvetlenül hozzá lehet adni egy alkatrészhez támasztóként.
Hogy mindezt működés közben lássa, íme egy példakód, amely lehetővé tenné a React számára, hogy az összes állapotmutációt egyetlen megjelenítésbe egyesítse, mutációnként egy renderelés helyett.
function Component() {
const [id, setId] = useState(0);
const [date, setDate] = useState(new Date());
const [random, setRandom] = useState(Math.random());
// A lame callback, but it's just for
// the demo. Note that clicking on the
// button will only lead to a single
// re-render!
//
// This is b/c the callback is provided to
// 'onClick', a synthetic event.
const onButtonClick = () => {
setDate(new Date());
setId(prevId => prevId + 1);
}
console.log("Render:", id, date);
return (
<div>
<button
onClick={onButtonClick}>
Update state
</button>
</div>
);
}
//
// Almost the same as the previous
// example, but this time w/o
// a batched upate call.
//
function Component() {
const [id, setId] = useState(0);
const [date, setDate] = useState(new Date());
const [random, setRandom] = useState(Math.random());
// No batching, as the state
// mutations happend inside
// a setTimeout - even though
// the timeout is inside a
// synthetic event.
const onButtonClick = () => {
setTimeout(() => {
setDate(new Date());
setId(prevId => prevId + 1);
}, 0);
}
console.log("Render:", id, date);
return (
<div>
<button
onClick={onButtonClick}>
Update state
</button>
</div>
);
}
Kötegelt frissítések a React 18 és újabb verzióihoz
A React következő verziójával (legalábbis amíg ezt írom) a kötegelési mechanizmus sokkal jobban javul. Ahelyett, hogy csak szintetikus eseményekben lenne lehetséges, más típusú visszahívások is használhatók lesznek.
- időtúllépések
- ígéretek
- natív eseménykezelők
Ez a módosítás nagy valószínűséggel az alkalmazás jobb teljesítményéhez vezet, mivel kevesebb megjelenítés történik automatikusan.
Kerülje a kötegelt frissítéseket a React 18 -ban és később
A React 18 -tól kezdve lehetősége lesz arra, hogy minden állapotmutációval kifejezetten új megjelenítést indítson el, elkerülve ezzel a kötegelt frissítést. Ezt valószínűleg csak szélső esetekben fogják használni, de ennek ellenére érdekes tudni.
//
// This example is almost
// 1:1 from Dan Abramov's
// example.
//
// Use 'flushSync' from the
// 'react-dom'-package.
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
setId(prevId => prevId + 1);
});
// React has updated the DOM by now
flushSync(() => {
setDate(new Date());
});
// React has updated the DOM by now
}