Главная / Статьи

Практическое применение Actions в React 19: для чего используются useActionState, use() и как работает компилятор Retire

React 19 и функции actions устраняют множество элементов кода: обработчики форм, оптимистичные обновления, forwardRef и ручная мемоизация. Какова польза от useActionState, use() и изменений в компиляторе?

Издатель: REACTAPP.TOP6 мин чтения1446 слов

Источники: React 19 Shipped Nine Months Ago. Most Teams Are Still Writing Code It Made Obsolete.

Многие команды просто увеличили номер версии React, не меняя ничего другого. Флаги загрузки, обработка ошибок и оптимистичные обновления, написанные ими много лет назад, до сих пор находятся в кодовой базе, поскольку обновление никогда не нарушало их работу. Оно лишь сделало их избыточными. Это экскурсия по вручную написанному коду, который теперь автоматически обрабатывает React 19.

Паттерн, который постоянно встречается

Если открыть практически любой компонент формы в проекте React 19, вы увидите одинаковую структуру. Здесь есть три состояния: одно для показа индикатора загрузки, одно для отображения ошибки и одно для указания на успешное выполнение. Существует асинхронный обработчик отправки, который вызывает e.preventDefault(), включает индикатор загрузки, удаляет старую ошибку, ожидает завершения запроса, в блоке try включает показ сообщения об успехе, в блоке catch копирует сообщение в раздел с ошибками и в блоке finally выключает индикатор загрузки.

Этот подход считается стандартом с момента популяризации React, и он действительно работает. Однако в React 19 он уже не нужен: теперь один хук отвечает за обработку задач, ошибок и результатов, включая упорядочивание последовательных запросов. Большинство команд этого даже не заметило, поскольку обновление не требовало изменений.

Что является стабильным, а что — нет

Сначала краткая справка: некоторые статьи описывают функции как уже доступные, хотя это не так.

Доступно в стабильной версии React 19.x:

  • Действия и хуки, построенные на них: useActionState, useFormStatus и useOptimistic.
  • API use() для чтения обещаний и контекста во время отрисовки.
  • ref как обычное свойство, из-за чего forwardRef становится устаревшим.
  • Метаданные документа в нативном формате: теги <title>, <meta> и <link>, генерируемые с помощью компонентов.
  • React Compiler, версия 1.0 которого вышла в октябре 2025 года и поддерживает версии React начиная с 17.
  • Дополнения в версии 19.2, такие как тег <Activity> и функция useEffectEvent.

На момент написания эти функции по-прежнему являются канарейскими или экспериментальными: компонент <ViewTransition> и ссылки на фрагменты. Считайте любые решения, использующие эти функции в готовых версиях, устаревшими, и проверяйте примечания к выпуску для конкретной установленной вами версии.

Actions: новая модель асинхронного состояния

Основной идеей React 19 является концепция Action — асинхронная функция, передаваемая в процесс перехода состояния. React берет на себя всё, что связано с этим процессом: обработку временного состояния, ошибок, оптимистичные обновления и сброс формы — всё то, что раньше командам приходилось писать вручную.

useActionState, useFormStatus и useOptimistic — это не три независимых функционала. Это три разных способа реализации одного и того же механизма.

useActionState заменяет подход с тремя флагами

Вместо использования трех состояний — загрузки, ошибки и успеха — вы пишете функцию Action, которая принимает предыдущее состояние и данные формы и возвращает следующее состояние. Эту функцию вместе с начальным состоянием передаётся в useActionState. Гук возвращает три элемента: текущее состояние, функцию для работы с формой и логическое значение isPending.

Затем компонент выполняет три простых действия. Атрибут action формы напрямую получает возвращаемую функцию. Кнопка отключается, пока значение isPending равно true. А любые сообщения считываются из возвращенного состояния. Нет состояния загрузки, нет состояния ошибки, нет блоков try, catch или finally, нет метода preventDefault, и нет необходимости вручную сбрасывать состояние.

Передача функции в атрибут action сделана намеренно. HTML-формы всегда имели атрибут action, и React 19 вновь его ввел. Это обеспечивает постепенное улучшение функционала: форма может быть отправлена даже без JavaScript, а React улучшает её поведение после загрузки скриптов.

useFormStatus позволяет кнопке узнавать информацию о своей форме

Самое удобное применение useFormStatus — это повторно используемая кнопка отправки. Внутри неё хук возвращает флаг pending, описывающий родительскую форму, без передачи каких-либо свойств. Кнопка отключается, а её метка меняется на что-то вроде «Сохранение», пока форма находится в состоянии ожидания. Поместив этот компонент где угодно внутри любой формы, он будет работать корректно, тем самым избавляя от необходимости передачи свойств через несколько уровней для очень распространённой задачи. Есть один недостаток: хук считывает статус формы, которая оборачивает компонент, поэтому он должен отображаться внутри формы, а не рядом с ней.

useOptimistic позволяет эффективно управлять мгновенной обратной связью

Оптимистичные обновления показывают пользователю ожидаемый результат сразу, ещё до подтверждения со стороны сервера, и автоматически корректируются при неудачной обработке запроса. При реализации вручную требуются временные идентификаторы, отдельный список задержанных элементов, логика объединения данных и код для возврата к предыдущему состоянию в случае ошибки. В таких случаях легко допустить скрытые ошибки.

С помощью useOptimistic вы передаёте хуку реальный список вместе с небольшим функционалом, описывающим, как добавить элемент с маркером задержки. Внутри обработчика формы вы вызываете функцию-установщик, возвращаемую хуком, а затем ожидаете завершения сохранения. Интерфейс сразу отображает новый элемент, возможно, с сниженной прозрачностью до момента подтверждения. По завершении обработки реальные данные заменяют оптимистичную копию, а при неудаче сохранения React сам возвращает систему в предыдущее состояние. Не требуется блок обработки ошибок или ручной возврат к предыдущему состоянию.

use(): условное загрузка ресурсов

use() — это новый API, который считывает ресурс, такой как обещание или контекст, во время отрисовки. В отличие от всех остальных хуков, его можно вызывать условно. Компонент может считать информацию о пользователе, сразу вернуться, если детали скрыты, и только затем считать предпочтения. Оберните структуру компонента в границы Suspense с альтернативным содержимым, и React будет приостанавливать отрисовку до поступления данных.

Существует одно важное ограничение: обещания, передаваемые в use(), должны оставаться неизменными между отрисовками. Поэтому их следует создавать вне компонента или использовать слой кэширования, такой как React Query или SWR, либо даже простой словарь на уровне модуля с ключами в виде ID. Обещания, создаваемые заново при каждой отрисовке, приведут к тому, что альтернативное содержимое будет отображаться вечно.

ref как свойство

Это изменение довольно простое. Теперь функциональные компоненты получают ref в качестве обычного свойства, поэтому его можно передавать непосредственно в базовый элемент ввода без использования forwardRef. Поведение остается прежним: уменьшается количество обёрток и импортов. Существующий код с forwardRef продолжит работать, поскольку отказ от его использования происходит постепенно и без сбоев, однако новые компоненты должны им не пользоваться.

Компилятор React

Компилятор — это самое незаметное обновление из всех. Он анализирует компоненты во время сборки и применяет механизмы кэширования, которые команды обычно реализуют вручную с использованием useMemo, useCallback и React.memo, делая это непоследовательно, или вообще их игнорируют. Вы пишете обычные компоненты, а компилятор правильно встраивает механизмы кэширования.

Чтобы попробовать это, установите плагин Babel babel-plugin-react-compiler и добавьте его в список плагинов в вашей конфигурации Babel. Поскольку он также поддерживает React 17 и 18, его можно внедрить без предварительного обновления React, что помогает командам, застрявшим на определённой версии, но желающим получить преимущества в производительности.

Замечание по безопасности для серверных компонентов

В начале 2026 года предупреждения о безопасности, касающиеся отказа в обслуживании и утечки исходного кода, затронули пакеты react-server-dom-*; для каждой поддерживаемой версии были выпущены исправленные версии. Если вы используете React Server Components, проверьте установленную версию с учётом текущих предупреждений и обеспечьте использование исправленной версии или новее. Не полагайтесь на память относительно того, какая версия считается безопасной.

Что делать на этой неделе

  • Новые формы: с самого начала используйте функцию useActionState — определите действие, передайте его в хук и прочитайте значение isPending из возвращаемых данных, полностью избегая ручного использования флагов.
  • Существующие обработчики: не переписывайте всё сразу. Выберите один из них, преобразуйте его в Action и посмотрите, как это будет работать. Улучшение читаемости обычно настолько очевидно, что позволяет самостоятельно определить приоритет миграции.
  • Компилятор: добавьте его в настройки сборки. Это небольшое изменение, которое работает с существующим кодом и не требует его переписывания, что делает его самым простым способом внедрения функций React 19 с наиболее значительным эффектом.
  • Компоненты серверной части: проверьте свою версию на наличие исправлений безопасности.

Сам заголовок привлёк внимание при публикации. Но настоящее изменение кроется внутри: использование Actions в качестве стандартной модели для любых асинхронных изменений состояния, что позволяет тихо устранить значительную часть кода, который разработчики React пишут каждый день. Многие команды уже обновились, но код всё ещё остаётся без изменений.