Learning
Všechny články
Frontend24. srpna 2026 6 min

Transition nic nezrychlí, jen dovolí práci zahodit

Označíš update jako přerušitelný, ne jako méně důležitý

Transition je souhlas s tím, že se práce zahodí

startTransition se často čte jako „udělej to na pozadí" nebo „udělej to později". Ani jedno nesedí. Callback se zavolá okamžitě a synchronně. Jediné, co se změní, je značka na updatech, které uvnitř vzniknou.

Ta značka říká: tenhle výsledek renderu smí React zahodit a spočítat znovu, když mezitím přijde něco naléhavějšího. Nic víc. Když si tohle položíš doprostřed, každé omezení v dokumentaci přestane být pravidlo k zapamatování a začne z toho plynout samo.


Proč musí být callback synchronní

React nemá jak zjistit, který setState „patří" k tvému transition, protože ho voláš přes referenci na set funkci kdekoli v kódu. Značkování proto funguje jako dynamický rozsah: React si po dobu volání callbacku nastaví příznak a všechny updaty, které v té chvíli vzniknou, ho zdědí.

Z toho plyne přesně to, co dokumentace uvádí jako omezení. Update uvnitř setTimeout označený nebude — příznak už dávno spadl. A po každém await musíš zbytek zabalit do dalšího startTransition, protože pokračování běží v jiném tiku.

Není to nedodělek API. Je to důsledek toho, že značka žije v čase, ne v uzávěře.


Kde to nesmíš použít

Řízený textový input. Dokumentace to zakazuje a důvod je přímý. Transition znamená, že React smí render zahodit a udělat znovu. U inputu, jehož value visí na stavu, by to znamenalo, že napsaný znak se na obrazovce objeví se zpožděním nebo problikne zpátky. Hodnota inputu musí být vždy naléhavá. Odložit se smí až to, co se z ní odvozuje — filtrovaný seznam, náhled, výsledky.

Stav, ke kterému nemáš set funkci. Když ti hodnota přichází z props nebo z cizího hooku, nemáš co obalit. Na to je useDeferredValue, který pracuje z druhé strany: nesnaží se update označit, ale nechá si u sebe starou hodnotu, dokud se nová nedopočítá.


isPending a co spolu ta tři API dělají

startTransition neříká, jestli něco běží. Chceš-li ukazatel načítání, potřebuješ useTransition, který je jinak totožný a navíc vrací isPending. Rozdíl je v tom, kde smí bydlet: startTransition funguje i mimo komponentu, třeba v datové knihovně, hook ne.

Dvě věci navíc stojí za pozornost. Update označený jako transition může být přerušen jiným updatem — to je celá pointa, ale znamená to, že se tvůj render callback může spustit vícekrát a nesmí mít vedlejší efekty. A pokud běží víc transitions naráz, React je aktuálně spojuje dohromady; nemáš tedy nástroj, jak sledovat jejich pořadí nebo je od sebe odlišit.


Co si z toho odnést

Neptej se, jestli je ten update důležitý. Ptej se, jestli je v pořádku jeho výsledek zahodit a spočítat znovu, když mezitím uživatel klikne jinam. Odpověď ano znamená transition, odpověď ne znamená nechat ho naléhavý.

Rozděl proto stav na dvě poloviny podle téhle otázky, ne podle toho, co je nákladné. Vstup od uživatele je vždy naléhavý, odvozený pohled skoro vždy může počkat. Právě proto se dvojice „naléhavý input plus odložený seznam" objevuje v příkladech pořád dokola — není to trik, je to jediné rozdělení, které tomu kontraktu vyhovuje.

A počítej s tím, že označení žije jen po dobu synchronního volání. Kdykoli mezi kliknutím a setState leží await, setTimeout nebo callback, musíš značku obnovit ručně. Jinak jsi napsal kód, který vypadá jako transition a chová se jako obyčejný update.

Zdroje

Poslech místo čtení — 3 zdroje k načtení.