[Перевод] Новые клиентские хуки React 19

jchwst6a3nwlxlscnmuw5tdhmry.png

Вопреки распространенному мнению, основная команда разработчиков 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!


b5pjofdoxth14ro-rjsrn7sbmiy.png

© Habrahabr.ru