Плавные асинхронные переходы в React 19
Вы создали форму, которая отправляет данные на сервер. Пользователь нажимает «Сохранить», и в течение двух секунд ничего не происходит. Он нажимает снова. Теперь у вас дублирующиеся запросы, запутанный интерфейс и разочарованный пользователь.
React 19 решает эту проблему с помощью асинхронных переходов — фундаментального изменения в том, как React обрабатывает асинхронные обновления. Вместо ручного управления состояниями загрузки, флагами ошибок и состояниями гонки, React теперь автоматически отслеживает ожидающую работу. В этой статье объясняется, чем useTransition в React 19 отличается от паттернов React 18, когда использовать эти примитивы и как они связаны с новыми браузерными API, такими как View Transitions.
Ключевые выводы
startTransitionв React 19 принимает асинхронные функции, автоматически отслеживая состояние ожидания во время выполнения перехода — это сокращает ручное переключениеisLoading.useTransitionкасается приоритета обновлений, а не анимации. Используйте его для отправки форм, фильтров поиска и переключения вкладок — но не для контролируемых полей ввода или срочных состояний ошибок.- Хук
useOptimisticхорошо сочетается с асинхронными переходами, чтобы мгновенно показывать ожидаемые результаты с автоматическим откатом при сбое. - Переходы планировщика React и браузерный API View Transitions решают разные задачи: один управляет когда обновления рендерятся, другой управляет как элементы анимируются между состояниями.
Как поддержка асинхронности в startTransition меняет всё
В React 18 startTransition принимал только синхронные функции. Вы могли помечать обновления состояния как низкоприоритетные, но асинхронные операции требовали отдельного управления состоянием загрузки.
React 19 это меняет. Теперь вы можете передавать асинхронные функции напрямую в startTransition:
const [isPending, startTransition] = useTransition()
const handleSubmit = () => {
startTransition(async () => {
const result = await saveToServer(data)
setStatus(result)
})
}
React отслеживает переход во время выполнения асинхронного действия. isPending остаётся true до тех пор, пока React не завершит обработку работы перехода.
Важно: обновления состояния, запланированные после await, не всегда могут автоматически включаться в тот же переход. Если вам нужно, чтобы эти обновления оставались несрочными, оберните их в ещё один startTransition.
Это устраняет большую часть шаблонного кода, который усложнял паттерны React 18:
| Паттерн React 18 | Паттерн React 19 |
|---|---|
Ручное состояние isLoading | Автоматическое отслеживание isPending |
| Try/catch с состоянием ошибки | Интеграция с error boundary |
| Обработка состояний гонки | Встроенная последовательность запросов |
useTransition в React 19: когда использовать
Используйте useTransition, когда хотите, чтобы интерфейс оставался отзывчивым во время дорогостоящих обновлений. Хук сообщает React: «Это обновление может подождать, если произойдёт что-то более срочное».
Хорошие случаи использования:
- Отправка форм, когда пользователи могут продолжать печатать
- Фильтры поиска, которые запускают загрузку данных
- Переключение вкладок, которое загружает новый контент
Пропустите переходы для:
- Значений контролируемых полей ввода (они должны обновляться немедленно)
- Критических состояний ошибок, которые требуют мгновенной видимости
- Простых синхронных изменений состояния
Ключевая идея: переходы касаются приоритета, а не анимации. React прервёт ожидающий переход, если пользователь печатает, прокручивает или выполняет любое срочное взаимодействие.
Оптимистичный UI в React 19 с useOptimistic
Хук useOptimistic естественным образом сочетается с асинхронными переходами. Он позволяет мгновенно показывать ожидаемые результаты, пока сервер подтверждает операцию:
const [optimisticItems, addOptimistic] = useOptimistic(
items,
(current, newItem) => [...current, newItem]
)
const handleAdd = () => {
startTransition(async () => {
addOptimistic({ id: "temp", text: inputValue })
await saveItem(inputValue)
})
}
Если запрос завершается неудачей, React автоматически откатывается к предыдущему состоянию. Это создаёт улучшение воспринимаемой производительности без сложной логики согласования состояния.
Хотя useOptimistic лучше всего работает вместе с переходами или асинхронными действиями, это не является строго обязательным — хук может использоваться независимо в зависимости от вашего потока данных.
Discover how at OpenReplay.com.
Переходы планировщика против View Transitions API
Переходы React и браузерный View Transitions API решают разные задачи:
Переходы планировщика (useTransition) управляют когда React рендерит обновления. Они обрабатывают приоритет и отзывчивость.
View transitions управляют как элементы анимируются между состояниями. Они обрабатывают визуальную непрерывность.
React экспериментирует с компонентом <ViewTransition>, который объединяет оба подхода. Однако это остаётся экспериментальным. Сам браузерный API имеет широкую поддержку в основных браузерах, включая Chrome, Edge, Safari и Firefox.
Если вы изучаете view transitions сегодня:
- Используйте
document.startViewTransition()с определением возможностей браузера - Предоставляйте изящные fallback для неподдерживаемых браузеров
- Избегайте использования экспериментальных интеграций фреймворков в production
Практические рекомендации
Делайте:
- Оборачивайте отправку форм и мутации данных в
startTransition - Используйте
isPendingдля отключения кнопок и отображения индикаторов загрузки - Комбинируйте с
useOptimisticдля мгновенной обратной связи при предсказуемых операциях
Не делайте:
- Не оборачивайте каждое обновление состояния в переход
- Не используйте переходы для срочной обратной связи UI, такой как ошибки валидации
- Не предполагайте, что View Transitions API работает везде
Заключение
Асинхронные переходы React 19 устраняют большую часть ручной логики состояния загрузки, которая загромождала приложения React 18. Передавая асинхронные функции в startTransition, вы получаете встроенное отслеживание состояния ожидания, более плавную воспринимаемую производительность и лучшую интеграцию с современными паттернами React.
Начните с замены ваших ручных состояний isLoading на useTransition. Добавьте useOptimistic там, где важна мгновенная обратная связь. Оставьте экспериментальную интеграцию View Transitions на тот момент, когда поддержка браузерами созреет.
Часто задаваемые вопросы
Да. В React 19 Server Actions, вызываемые из клиентских компонентов, могут быть обёрнуты в startTransition. Это позволяет отслеживать состояние ожидания серверных мутаций напрямую с клиента, предоставляя автоматическое отслеживание isPending без дополнительных переменных состояния загрузки.
Ошибки, выброшенные во время перехода, распространяются к ближайшей error boundary, если она существует. Без error boundary ошибка проявится как любая другая ошибка рендеринга, поэтому production-приложения должны обеспечить наличие boundaries. Любые оптимистичные обновления, сделанные через useOptimistic, обычно откатываются, когда переход прерывается.
Да. Хотя обычно используется в паре с переходами или асинхронными действиями, useOptimistic может функционировать самостоятельно. Сочетание с переходами просто улучшает воспринимаемую отзывчивость во время несрочных обновлений.
Не обязательно. useTransition помечает обновления как несрочные, что означает, что React может отложить их рендеринг. В случаях, когда вам нужна немедленная обратная связь UI, например, ошибки валидации или переключение модального окна, простой булевый useState всё ещё является правильным выбором. Оставьте переходы для операций, где отзывчивость важнее немедленности.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.