Новая функциональность в React 19 направлена, прежде всего, на улучшение:
- Управления состоянием.
- Обработки ошибок.
- Работы с асинхронными операциями.
Рассмотрим ключевые улучшения подробнее.
Действия (Actions)
Действия предназначены для обработки асинхронных запросов и автоматизации управления отложенными состояниями, ошибками и оптимистичными обновлениями. Фронтендеры теперь могут работать с асинхронными операциями более интуитивно, сохраняя пользовательский интерфейс отзывчивым в любое время – даже когда запросы выполняются в реальном времени.
Мониторинг состояния с помощью переменных типа isPending или isLoading во время асинхронных операций теперь можно заменить новым хуком useTransition.
UseTransition позволяет обновлять состояние компонента без блокировки пользовательского интерфейса. Другими словами, приложение будет работать и откликаться на действия пользователя при выполнении асинхронных операций в фоновом режиме, например, сетевых запросов. Пример использования:
Важно отметить, что startTransition объединяет все изменения состояния. Это значит, что любые обновления состояния, которые происходят внутри startTransition, не приведут к перерисовке интерфейса до тех пор, пока весь код внутри этого блока не выполнится. Например, в приведенном выше примере вызывается только одна функция – setError. Но если бы их было больше, все изменения состояния произойдут за один раз в конце. Это делает useTransition очень полезным, потому что он вызывает только одно обновление пользовательского интерфейса вместо нескольких. Если у вас внутри функции handleSubmit происходит несколько изменений состояния, например, N изменений, то без startTransition интерфейс обновлялся бы N раз, а с ним – только один раз.
Ранее приходилось вручную отслеживать состояние загрузки. До появления useTransition для отслеживания завершения операции, как в примере с updateName, нужно было использовать переменную состояния, например, isPending. Это выглядело бы так:
Предположим, что между моментами, когда isPending сбрасывается в false и когда проверяется ошибка (через if(error)), в приложении выполняется несколько асинхронных операций. Раньше это могло бы привести к негативному пользовательскому опыту – интерфейс обновился бы раньше, чем закончилась вся работа с данными, и пользователь увидел бы неполную информацию. Но при использовании startTransition такой проблемы не возникнет, потому что он вызывает обновление состояния только один раз – после того, как завершатся все операции. Это делает работу с асинхронными действиями более предсказуемой и даже упрощает код, убирая лишнюю строчку.
Улучшенная работа с формами
В React 19 появился новый хук useActionState, который предоставляет разработчикам встроенную поддержку для обработки состояний и отправки формы. Этот хук позволяет автоматически управлять состояниями и результатами:
Несколько важных моментов в этом примере:
- Код внутри useActionState – это код действия. Все, что находится внутри хука useActionState, выполняется при отправке формы (или при каком-либо действии). Это, по сути, логика, которая выполняется при событии, например, при нажатии кнопки «Отправить».
- formData не является типобезопасным. При вызове formData.get(name) нет гарантии, что будет возвращен текст. Может вернуться что угодно, и данные могут быть некорректными. Чтобы избежать ошибок, можно создать свой кастомный хук, который использует useActionState вместе с валидатором данных. Это позволит проверить данные перед отправкой на сервер (API).
- submitAction передается напрямую в свойство action элемента.
- useActionState создан специально для действий, особенно для работы с формами. Этот хук полезен, когда нужно управлять состоянием действий (например, отправкой формы), делая код более чистым и организованным.
Кроме useActionState, появился еще один полезный хук – useFormStatus. Он упрощает работу с элементами формы в React 19. С его помощью разработчики могут получать информацию о состоянии формы в дочерних компонентах, не передавая вручную пропсы и не используя контексты – это делает работу с формами более простой и интуитивной:
useFormStatus предоставляет доступ к четырем свойствам формы (pending, data, method и action):
Важно отметить, что только дочерние компоненты элемента формы смогут получить доступ к этим свойствам, т. е. DesignButton является дочерним компонентом в приведенном выше примере.
Оптимистические обновления
Оптимистические обновления – это способ мгновенно показать пользователю предполагаемый финальный результат в интерфейсе, даже если в фоновом режиме продолжается обработка данных. Это делает приложение более отзывчивым, особенно в случаях плохого соединения или долгих запросов. Если при выполнении возникает ошибка, интерфейс возвращается к исходному состоянию.
В React 19 можно реализовать оптимистические обновления с помощью нового хука useOptimistic:
Важные моменты:
- useOptimistic работает как useState – он принимает начальное значение (в данном случае это currentName) и позволяет его изменять.
- Если отправка данных завершится ошибкой, React автоматически вернет значение optimisticName обратно к currentName. Это обеспечивает безопасность данных – если что-то пойдет не так, пользователь увидит реальное состояние данных.
API use
В React 19 появилась новая возможность – использовать API use для работы с ресурсами, такими как промисы и контексты, прямо внутри функции рендеринга. Это новшество позволяет использовать use даже в условных конструкциях, что ранее было невозможно с хуками. Благодаря этому разработчики могут эффективнее управлять зависимостями данных и создавать более динамичные приложения. Пример работы с промисами:
Важные моменты:
- Когда используется промис, use приостановит выполнение компонента до тех пор, пока промис не завершится. Это удобно для сетевых запросов, где данные еще загружаются. Вместе с компонентом Suspense, можно показывать фолбэк (например, сообщение о загрузке) до завершения запроса.
- Нельзя использовать промисы, созданные прямо в рендере. Если промис создается в процессе рендеринга, use не сможет его обработать. Промис должен быть заранее подготовлен и закэширован или должен использовать совместимые с Suspense библиотеки.
Пример работы с контекстом и условным рендерингом:
Важные моменты:
- В отличие от других хуков, use можно использовать в условных операторах (но не в блоке try-catch). Как в примере выше, для переключения тем оформления можно использовать use в зависимости от условий (темная или светлая тема).
- Нет необходимости в явных потребителях контекста. Вместо того чтобы использовать компоненты-контекстные потребители (Context.Consumer), теперь можно просто вызвать use для получения значения контекста прямо в компоненте, даже в условных выражениях. Также, как и useContext, use находит ближайший провайдер контекста, который находится выше по дереву компонентов.
Серверные компоненты
Server Components в React 19 – новый способ рендеринга компонентов: рендеринг происходит заранее, либо один раз во время сборки, либо при каждом запросе на сервере, который отделен от клиентской части приложения. Похожим образом реализован серверный рендеринг в Next.js.
С помощью серверных компонентов разработчики могут контролировать, когда создается HTML-страница: на сервере, во время сборки или в процессе выполнения запроса. Это дает больше гибкости и возможностей для оптимизации.
Раньше для получения статических данных, например, из CMS (системы управления контентом), часто использовали хук useEffect. Подобный код выполнялся после первого рендеринга страницы:
Проблема в том, что при этом:
- Клиент загружает лишние библиотеки (например, 75 КБ для работы с Markdown и его очистки).
- Данные загружаются после первого рендеринга страницы, что делает интерфейс медленнее.
Теперь все это можно загрузить сразу на сервере во время рендеринга, и клиенту не нужно ждать второй запрос или загружать лишние библиотеки:
Серверные действия
Server Actions – это новая функция в React, позволяющая компонентам на клиенте вызывать асинхронные функции, выполняемые на сервере. Она создает связь между клиентом и сервером с помощью директивы use server. Это своего рода туннель, через который клиент может отправлять данные серверу для обработки.
Server Actions создаются в Server Components и могут передаваться в компоненты клиента как свойства (пропсы) или импортироваться и использоваться напрямую в Client Components.
Директива use server не указывает, что это компонент сервера, а создает связь между сервером и клиентом. Подобно тому, как use client говорит React отправлять JavaScript-код на клиент, use server создает «туннель», через который клиент может отправлять данные на сервер для обработки.
Допустим, у нас есть серверный компонент для создания заметок в базе данных. Этот компонент передает действие на клиент для выполнения по нажатию кнопки:
Когда React рендерит компонент EmptyNote, он создает ссылку на функцию createNoteAction и передает ее в клиентский компонент Button. Когда пользователь нажимает кнопку, React отправляет запрос на сервер для выполнения этой функции. Клиентский компонент выглядит так:
Также можно вынести серверное действие в отдельный файл и импортировать его:
Клиентский код:
Преимущества Server Actions:
- Повышение производительности. Поскольку часть логики выполняется на сервере, это снижает нагрузку на клиент и ускоряет начальную загрузку страниц. Особенно это важно для крупных приложений, которым нужно обрабатывать много данных.
- Улучшение SEO. Данные могут быть подготовлены на сервере заранее, что делает содержимое доступным для поисковых систем.
- Повышение модульности и переиспользуемости. Возможность использовать как серверные, так и клиентские действия улучшает организацию кода и упрощает повторное использование логики в разных местах приложения.
React 19 привносит революционные изменения в мир фронтенд-разработки. Если вы хотите быть на гребне волны и освоить не только новые возможности React, но и фундаментальные основы современного веба, обратите внимание на курс Frontend Basic от Proglib Academy. Вот что вы получите:
- Понимание принципов работы современного веба
- Практический опыт создания интернет-магазина с нуля
- Знания, необходимые для работы с новейшими технологиями, включая React
- Возможность быстро адаптироваться к изменениям в мире фронтенд-разработки
Комментарии