[Перевод] Новые клиентские хуки React 19
Вопреки распространенному мнению, основная команда разработчиков React занимается не только серверными компонентами React
и Next.js. В следующей версии — React 19
— появятся новые клиентские хуки. Они сфокусированы на двух ключевых аспектах: выборке данных и работе с формами. Эти хуки повысят производительность всех React-разработчиков, включая тех, кто создает одностраничные приложения.
Без дальнейших предисловий давайте познакомимся с новыми хуками!
- use (Promise)
- use (Context)
- Form Actions
- useFormState
- useFormStatus
- useOptimistic
- Бонус: Async Transitions
Примечание: эти хуки доступны только в экспериментальной (canary) версии React. Они должны быть включены в новую версию React 19
, но до финального релиза в API возможны изменения.
use (Promise)
Этот хук представляет собой официальное API для «ожидания данных» (suspending) на клиенте. Ему можно передать промис, и React
будет ждать его выполнения. Основной синтаксис, взятый из документации React, выглядит следующим образом:
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
// ...
}
Хорошая новость заключается в том, что этот хук можно использовать для выборки данных (data fetching). Вот пример запроса данных при монтировании компонента и нажатии на кнопку. Обратите внимание, что в коде не используется хук useEffect
:
Помните это предупреждение в документации
?
Выборка данных с поддержкой Suspense без самодостаточного фреймворка не поддерживается.
Но в React 19
это больше не актуально.
Хук use
обладает интересной особенностью: в отличие от других хуков React
, его можно вызывать внутри циклов и условных операторов, таких как if
.
Означает ли это, что для получения данных на клиенте больше не нужно использовать сторонние библиотеки, например, TanStack Query? Что ж, нам еще предстоит это выяснить, поскольку TanStack Query делает гораздо больше, чем просто разрешает промис.
Но это шаг в правильном направлении, который значительно упрощает создание одностраничных приложений, работающих с REST
или GraphQL API
. Я в восторге от этого нового хука!
Подробнее о хуке use(Promise)
читайте здесь.
use (Context)
Хук use
также можно использовать для чтения контекста React
. Он работает аналогично хуку useContext
, за исключением того, что его можно вызывать внутри циклов и условных операторов, таких как if
.
import { use } from 'react';
function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return
;
}
return false;
}
Это упрощает иерархию компонентов в некоторых вариантах использования. Ранее, чтобы прочитать контекст в таких случаях, приходилось разделять компонент на две части.
Это значительно улучшает производительность, поскольку теперь можно условно пропустить повторный рендеринг компонента, даже если значение контекста изменилось.
Подробнее о хуке use(Context)
читайте здесь.
Form Actions
Эта фича позволяет передавать функцию в проп action
тега .
React
будет вызывать эту функцию при каждой отправке формы:
Однако, если добавить проп action
со значением в виде функции в React 18
, появится такое предупреждение:
Предупреждение: недопустимое значение для пропаaction
в теге. Либо удалите этот проп, либо передайте в него строковое или числовое значение.
Однако, в React 19
это больше не проблема, и можно реализовать такую форму:
Функция addToCart
не является серверной операцией (server action). Она вызывается на клиенте и может быть асинхронной.
Это значительно упрощает обработку форм в React
— например, формы поиска. Возможно, этого недостаточно для полного отказа от сторонних библиотек, таких как React Hook Form, которые предлагают гораздо больше функциональности, чем просто обработку отправки формы (валидация, побочные эффекты и т.д.).
Подробнее о пропе action
читайте здесь.
useFormState
Этот новый хук предназначен для упрощения работы с асинхронным . Вызов
useFormState()
возвращает значение последней операции отправки формы.
import { useFormState } from 'react-dom';
import { action } from './action';
function MyComponent() {
const [state, formAction] = useFormState(action, null);
// ...
return ;
}
Вот как можно отобразить подтверждение или сообщение об ошибке, возвращаемое :
Обратите внимание: useFormState
должен импортироваться из react-dom
, а не из react
.
Подробнее о хуке useFormState
читайте здесь.
useFormStatus
useFormStatus
позволяет определить статус отправки родительской формы. Этот хук можно вызывать в дочерних элементах формы, и он возвращает объект со следующими свойствами:
const { pending, data, method, action } = useFormStatus();
data
позволяет отобразить данные, отправляемые пользователем. pending
позволяет блокировать кнопку на время отправки формы:
Обратите внимание: useFormState
должен импортироваться из react-dom
, а не из react
. Кроме того, данный хук работает только в том случае, если у родительской указан проп
action
со значением в виде функции.
Вместе с useFormState
этот новый хук помогает улучшить взаимодействие пользователей с формами без лишних эффектов, усложняющих компоненты.
Подробнее о хуке useFormStatus
читайте здесь.
useOptimistic
Этот новый хук позволяет оптимистично обновлять пользовательский интерфейс во время выполнения операции.
import { useOptimistic } from 'react';
function AppContainer() {
const [optimisticState, addOptimistic] = useOptimistic(
state,
// Функция обновления UI
(currentState, optimisticValue) => {
// Объединяем и возвращаем новое состояние
// с оптимистичным значением
},
);
}
В следующем примере показано использование useOptimistic
для обновления корзины товаров до завершения отправки формы.
Оптимистичное обновление UI — отличный способ улучшить впечатление пользователей от работы с приложением.
Подробнее о хуке useOptimistic
читайте здесь.
Бонус: Async Transitions
Transition API
в React
позволяет плавно обновлять состояние без блокировки UI. Например, он позволяет отменить изменение состояния в случае, если пользователь передумал.
Чтобы использовать Transition API
, нужно обернуть изменение состояния в функцию startTransition
:
function TabContainer() {
const [isPending, startTransition] = useTransition();
const [tab, setTab] = useState('about');
function selectTab(nextTab) {
// Вместо setTab(nextTab)
startTransition(() => {
setTab(nextTab);
});
}
// ...
}
В следующем примере Transition API
используется для переключения вкладок. Если нажать на «Posts» и сразу после этого на «Contact», то медленное отображение «Posts» прервется, и контент вкладки «Contact» отобразится мгновенно. Благодаря тому, что это изменение состояния помечено как переход (transition), медленный рендеринг не приводит к блокировке UI.
Хук useTransition
доступен в React 18.2
. Новшество в React 19
заключается в том, что в startTransition()
можно передавать асинхронную функцию, которую React
будет ждать для запуска перехода.
Это особенно полезно при отправке данных с помощью AJAX-запросов
и отображении результата после перехода. Переход начинается с асинхронной отправки данных. Это можно использовать в фиче form actions
, описанной выше. React
будет вызывать обработчик , обернутый в
startTransition
, не блокируя текущую страницу.
Описания этой фичи пока нет в документации React
, но прочитать о ней больше можно в этом pull request.
Заключение
Все описанные хуки работают только в клиентских приложениях React
, например, созданных с помощью Vite. Для их использования не требуется серверный рендеринг, предоставляемый такими фреймворками, как Next.js
или Remix.
Эти хуки существенно облегчают выборку данных и обработку форм в React
. Однако для обеспечения хорошего пользовательского опыта требуется бесшовная и плотная интеграция всех этих обработчиков, что может быть проблематичным. В качестве альтернативы можно использовать фреймворк, например, react-admin, в который встроены удобные для пользователя формы с оптимистичными обновлениями.
Почему эти фичи появляются в React 19
, а не в React 18.3
? Похоже, что версии 18.3
просто не будет.
Официальная дата релиза React 19
пока неизвестна, но все фичи, упомянутые в статье, уже работают. Однако, использовать их в продакшене пока не рекомендуется, так как использование экспериментальной версии React
не очень хорошая идея (даже если Next.js
так делает).
Приятно видеть, что команда React
работает над улучшением опыта всех разработчиков, а не только тех, кто работает с серверным рендерингом. Также важно отметить, что они прислушиваются к отзывам сообщества. Выборка данных и обработка форм — головная боль многих разработчиков.
Я с нетерпением жду появления этих фич в стабильной версии React
!