# Гид по React 19: Actions, новый компилятор и API use

Источник: https://www.youtube.com/watch?v=81uAxzeyL2I
Канал: freeCodeCamp.org
Опубликовано: 25.06.2024

---

React 19 приносит множество долгожданных нововведений, которые призваны упростить работу с асинхронными данными, оптимизировать производительность приложений и избавить разработчиков от рутинного кода. Фронтенд-инструктор платформы Scrimba Боб Зиролл в своем практическом мини-курсе подробно разбирает ключевые изменения новой мажорной версии, находящейся в статусе Release Candidate. В центре внимания — автоматический компилятор, концепция Actions, новые специализированные хуки и уникальный API `use`.

## ⏳ Эволюция управления состоянием: от переходов к операциям
[[JUMP:02:25]]

Для понимания ключевых новшеств React 19 необходимо разобраться в концепции переходов (Transitions), появившейся еще в React 18. Боб Зиролл демонстрирует проблему на примере переключения вкладок интерфейса: при переходе на вкладку «Продукты» компонент генерирует список из 1500 элементов с искусственной задержкой отрисовки в 1 миллисекунду на элемент с помощью библиотеки Faker JS, что суммарно дает задержку в 1,5 секунды. Если пользователь кликает на медленную вкладку, а затем сразу выбирает другую, стандартный механизм React выстраивает обновления в очередь и блокирует интерфейс до завершения тяжелого рендеринга.

Использование хука `useTransition` решает эту проблему, указывая React, что определенные изменения состояния имеют низкий приоритет и могут быть прерваны. 

Хук возвращает массив из двух элементов:

* `isPending` — булево значение, сигнализирующее о выполнении перехода в фоне.
* `startTransition` — функция-обертка для низкоприоритетных обновлений состояния.

Благодаря встроенному флагу `isPending` разработчикам больше не требуется вручную создавать громоздкий бойлерплейт с `useState` для отслеживания состояния загрузки. Интерфейс становится отзывчивым, сбрасывая тяжелые фоновые задачи, если пользователь передумал и кликнул на другую вкладку.

## 🛠️ Автоматическая оптимизация с React Compiler
[[JUMP:11:25]]



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

По словам Боба Зиролла, с полноценным внедрением компилятора у разработчиков отпадет необходимость в ручном управлении мемоизацией. В частности, можно будет практически полностью отказаться от использования следующих инструментов:

* `react.memo`
* `useMemo`
* `useCallback`

На момент записи курса документация компилятора находилась в стадии бета-тестирования, однако проект уже полностью открыт для сообщества (open-source). Компилятор берет на себя всю рутину по вычислению потенциальных узких мест производительности программы.

## 📦 Концепция Actions и нативная работа с формами
[[JUMP:13:08]]

Важным архитектурным изменением стало появление концепции Actions, ориентированной на обработку мутаций данных. В официальной документации React под «действиями» (Actions) понимаются функции, использующие асинхронные переходы. Боб Зиролл отмечает, что это определение может показаться запутанным, но на практике оно сводится к нативному способу изменения данных в экосистеме React.

Первое и наиболее очевидное применение Actions — передача функции напрямую в проп `action` стандартного HTML-элемента `<form>`. По мнению спикера, в традиционном React управление формами всегда считалось одной из самых проблемных зон. Разработчикам приходилось выполнять много рутинных действий:

1.  Контролировать каждый ввод через связку параметров `value` и `onChange` для обновления локального состояния на каждый символ.
2.  Вручную вызывать `event.preventDefault()` в обработчике `onSubmit`, чтобы избежать перезагрузки страницы браузером.
3.  Императивно обрабатывать состояния отправки, сброса полей и ошибок.

React 19 предлагает кардинально иной подход. Функция, переданная в проп `action`, автоматически принимает нативный объект `FormData`. Это позволяет извлекать данные по атрибуту `name` с помощью метода `formData.get('name')`, избавляя от необходимости синхронизировать ввод с состоянием компонента и вручную отменять стандартное поведение отправки формы.

## 🔄 Управление асинхронным состоянием с помощью useActionState
[[JUMP:23:32]]

Для обработки комплексных сценариев отправки форм, включающих отслеживание ошибок и стадий загрузки, в React 19 представлен специализированный хук `useActionState`. Этот инструмент автоматизирует управление жизненным циклом асинхронной операции.

Синтаксис хука `useActionState` возвращает кортеж из трех элементов:

* Текущее состояние (`state`).
* Обернутая функция действия для привязки к форме (`formAction`).
* Флаг активности процесса (`isPending`).

Принцип работы передаваемой функции во многом напоминает редюсеры в Redux или стандартный хук `useReducer`. Функция принимает два аргумента: предыдущее состояние компонента (`previousState`) и объект `formData`. Результат выполнения функции автоматически становится новым состоянием.

Для полноценного отслеживания ошибок Боб Зиролл рекомендует переводить состояние с примитивного уровня (строки) на уровень объектов. Это позволяет хранить одновременно и полезные данные, и сообщения об ошибках. Спикер подчеркивает важность явного копирования или сохранения свойств предыдущего состояния (например, через деструктуризацию), чтобы избежать перезаписи и потери актуальных данных при возникновении ошибок.

## 🚀 Мгновенный отклик интерфейса с useOptimistic
[[JUMP:41:59]]

Статистически подавляющее большинство запросов к базам данных завершаются успешно, поэтому долгое ожидание ответа сервера ухудшает пользовательский опыт. Хук `useOptimistic` позволяет мгновенно обновить UI, предполагая успешный исход операции, и автоматически откатить изменения в случае сбоя.

Боб Зиролл приводит аналогию с современными социальными сетями, например, Twitter: когда пользователь нажимает кнопку «лайк», сердечко окрашивается моментально, а фактический запрос выполняется в фоновом режиме. 

Реализация оптимистичного обновления требует интеграции хука в цепочку вызовов Actions:

1.  Инициализируется состояние: `const [optimisticName, setOptimisticName] = useOptimistic(state.name);`.
2.  Внутри асинхронной функции, *до* выполнения сетевого запроса, вызывается `setOptimisticName(formData.get('name'))`.
3.  В интерфейсе пользователю выводится переменная `optimisticName`.

Если фоновый запрос падает с ошибкой, React самостоятельно возвращает значение к исходному `state.name` и отображает ошибку. По мнению спикера, такой подход делает приложение субъективно гораздо более «отзывчивым» и избавляет от необходимости показывать навязчивые индикаторы загрузки.

## 🔌 Инкапсуляция контекста формы через useFormStatus
[[JUMP:47:31]]

При проектировании библиотек компонентов или глубоко вложенных элементов форм возникает проблема передачи состояния загрузки (prop drilling). Создание собственного React-контекста для этой задачи усложняет архитектуру. Решением становится новый хук `useFormStatus`.

Этот хук работает как автоматический потребитель контекста (context consumer) ближайшей родительской формы. Важной особенностью является то, что `useFormStatus` импортируется из пакета `react-dom`, а не из ядра `react`. Боб Зиролл объясняет это тем, что превращение HTML-формы в провайдер контекста завязано непосредственно на работу с DOM-деревом.

Вызов хука возвращает объект со следующими свойствами:

* `pending` — статус отправки формы.
* `data` — экземпляр `FormData`, отправляемый в данный момент.
* `method` — HTTP-метод формы (например, GET или POST).
* `action` — ссылка на саму функцию действия.

Это позволяет легко создавать кастомные кнопки отправки, которые самостоятельно меняют свой текст на «Отправка...» или блокируются, не требуя передачи пропсов сверху.

## 🎯 Прямая передача рефов (Refs) как обычных пропсов
[[JUMP:52:12]]

Рефы в React используются для сохранения информации между рендерами без инициации повторного рендеринга, чаще всего — для хранения ссылок на нативные DOM-узлы (например, для программной установки фокуса на инпуте).

В React 18 и более ранних версиях прямая передача рефа в дочерний кастомный компонент была невозможна. Разработчикам приходилось использовать специальную функцию-обертку `forwardRef`, которая передавала реф вторым параметром функции компонента. Команда React позиционировала это как временное решение.

В React 19 API библиотеки было оптимизировано: теперь `ref` является обычным пропсом наряду с `children` и другими параметрами. Больше нет необходимости использовать `forwardRef`, что существенно упрощает код кастомных библиотек компонентов.

## 🔮 Универсальный API use для асинхронных ресурсов
[[JUMP:55:05]]



Одним из самых обсуждаемых и необычных нововведений стал API под названием `use`. Боб Зиролл обращает внимание на критически важный нюанс: это именно API, а не хук, поэтому он не подчиняется строгим правилам хуков. Его можно вызывать условно — внутри блоков `if` или циклов.

Инструмент предназначен для чтения асинхронных ресурсов (промисов) или контекста прямо во время рендеринга. До появления `use` загрузка данных в чистом React требовала использования хука `useEffect` при монтировании компонента и сохранения результата в локальное состояние `useState`.

С помощью `use` код можно писать в квази-синхронном стиле: `const data = use(fetchPromise)`. При вызове этой инструкции компонент автоматически «приостанавливает» свой рендеринг (suspends). Для корректной работы приложение обязательно должно быть обернуто в компонент `<Suspense>` с указанием резервного интерфейса (fallback), который будет показываться во время ожидания данных.

Тем не менее, спикер предупреждает о текущем жестком ограничении: создание промисов (например, вызов `fetch()`) непосредственно внутри тела клиентского компонента на каждом рендере приведет к бесконечным запросам и вызовет предупреждение об «некэшированном промисе». На текущем этапе для использования `use` необходимы внешние библиотеки или фреймворки, поддерживающие кэширование промисов, хотя в будущем команда React планирует добавить нативный механизм кэширования в рендере.

## 📑 Автоматический подъем метаданных документа
[[JUMP:1:04:10]]

Завершая обзор, Боб Зиролл выделил встроенную поддержку метаданных документа. Традиционно в React-приложениях компоненты рендерят контент внутрь корневого элемента (обычно `<div id="root">`), расположенного в теге `<body>`, из-за чего прямого доступа к тегу `<head>` нет. Для динамического изменения заголовков страниц в целях SEO приходилось подключать сторонние библиотеки, такие как `react-helmet`.

В React 19 разработчики могут объявлять теги `<title>`, `<meta>` и `<link>` в любом месте компонентного дерева. React автоматически перенесет (hoist) эти элементы в заголовок документа `<head>`. Это существенно упрощает базовую SEO-оптимизацию веб-страниц без привлечения лишних внешних зависимостей.