Frog Proger 16 сентября 2024

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Обзор ключевых нововведений в React 19: Actions, useTransition, Server Components и другие инструменты для улучшения производительности и упрощения разработки.
⚛️🔄 Улучшенная обработка асинхронных операций в React 19
Этот материал взят из нашей еженедельной email-рассылки, посвященной фронтенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

Новая функциональность в React 19 направлена, прежде всего, на улучшение:

  • Управления состоянием.
  • Обработки ошибок.
  • Работы с асинхронными операциями.

Рассмотрим ключевые улучшения подробнее.

Действия (Actions)

Действия предназначены для обработки асинхронных запросов и автоматизации управления отложенными состояниями, ошибками и оптимистичными обновлениями. Фронтендеры теперь могут работать с асинхронными операциями более интуитивно, сохраняя пользовательский интерфейс отзывчивым в любое время – даже когда запросы выполняются в реальном времени.

Мониторинг состояния с помощью переменных типа isPending или isLoading во время асинхронных операций теперь можно заменить новым хуком useTransition.

UseTransition позволяет обновлять состояние компонента без блокировки пользовательского интерфейса. Другими словами, приложение будет работать и откликаться на действия пользователя при выполнении асинхронных операций в фоновом режиме, например, сетевых запросов. Пример использования:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Важно отметить, что startTransition объединяет все изменения состояния. Это значит, что любые обновления состояния, которые происходят внутри startTransition, не приведут к перерисовке интерфейса до тех пор, пока весь код внутри этого блока не выполнится. Например, в приведенном выше примере вызывается только одна функция – setError. Но если бы их было больше, все изменения состояния произойдут за один раз в конце. Это делает useTransition очень полезным, потому что он вызывает только одно обновление пользовательского интерфейса вместо нескольких. Если у вас внутри функции handleSubmit происходит несколько изменений состояния, например, N изменений, то без startTransition интерфейс обновлялся бы N раз, а с ним – только один раз.

Ранее приходилось вручную отслеживать состояние загрузки. До появления useTransition для отслеживания завершения операции, как в примере с updateName, нужно было использовать переменную состояния, например, isPending. Это выглядело бы так:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19
Внимание
Обратите внимание, что при использовании такого подхода может возникнуть ситуация, когда состояние isPending будет установлено в false, но ошибка еще не произошла.

Предположим, что между моментами, когда isPending сбрасывается в false и когда проверяется ошибка (через if(error)), в приложении выполняется несколько асинхронных операций. Раньше это могло бы привести к негативному пользовательскому опыту – интерфейс обновился бы раньше, чем закончилась вся работа с данными, и пользователь увидел бы неполную информацию. Но при использовании startTransition такой проблемы не возникнет, потому что он вызывает обновление состояния только один раз – после того, как завершатся все операции. Это делает работу с асинхронными действиями более предсказуемой и даже упрощает код, убирая лишнюю строчку.

Улучшенная работа с формами

В React 19 появился новый хук useActionState, который предоставляет разработчикам встроенную поддержку для обработки состояний и отправки формы. Этот хук позволяет автоматически управлять состояниями и результатами:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Несколько важных моментов в этом примере:

  1. Код внутри useActionState – это код действия. Все, что находится внутри хука useActionState, выполняется при отправке формы (или при каком-либо действии). Это, по сути, логика, которая выполняется при событии, например, при нажатии кнопки «Отправить».
  2. formData не является типобезопасным. При вызове formData.get(name) нет гарантии, что будет возвращен текст. Может вернуться что угодно, и данные могут быть некорректными. Чтобы избежать ошибок, можно создать свой кастомный хук, который использует useActionState вместе с валидатором данных. Это позволит проверить данные перед отправкой на сервер (API).
  3. submitAction передается напрямую в свойство action элемента.
  4. useActionState создан специально для действий, особенно для работы с формами. Этот хук полезен, когда нужно управлять состоянием действий (например, отправкой формы), делая код более чистым и организованным.

Кроме useActionState, появился еще один полезный хук – useFormStatus. Он упрощает работу с элементами формы в React 19. С его помощью разработчики могут получать информацию о состоянии формы в дочерних компонентах, не передавая вручную пропсы и не используя контексты – это делает работу с формами более простой и интуитивной:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

useFormStatus предоставляет доступ к четырем свойствам формы (pending, data, method и action):

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Важно отметить, что только дочерние компоненты элемента формы смогут получить доступ к этим свойствам, т. е. DesignButton является дочерним компонентом в приведенном выше примере.

Оптимистические обновления

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

В React 19 можно реализовать оптимистические обновления с помощью нового хука useOptimistic:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Важные моменты:

  1. useOptimistic работает как useState – он принимает начальное значение (в данном случае это currentName) и позволяет его изменять.
  2. Если отправка данных завершится ошибкой, React автоматически вернет значение optimisticName обратно к currentName. Это обеспечивает безопасность данных – если что-то пойдет не так, пользователь увидит реальное состояние данных.
👨‍💻🎨 Библиотека фронтендера
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека фронтендера»

API use

В React 19 появилась новая возможность – использовать API use для работы с ресурсами, такими как промисы и контексты, прямо внутри функции рендеринга. Это новшество позволяет использовать use даже в условных конструкциях, что ранее было невозможно с хуками. Благодаря этому разработчики могут эффективнее управлять зависимостями данных и создавать более динамичные приложения. Пример работы с промисами:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Важные моменты:

  1. Когда используется промис, use приостановит выполнение компонента до тех пор, пока промис не завершится. Это удобно для сетевых запросов, где данные еще загружаются. Вместе с компонентом Suspense, можно показывать фолбэк (например, сообщение о загрузке) до завершения запроса.
  2. Нельзя использовать промисы, созданные прямо в рендере. Если промис создается в процессе рендеринга, use не сможет его обработать. Промис должен быть заранее подготовлен и закэширован или должен использовать совместимые с Suspense библиотеки.

Пример работы с контекстом и условным рендерингом:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Важные моменты:

  1. В отличие от других хуков, use можно использовать в условных операторах (но не в блоке try-catch). Как в примере выше, для переключения тем оформления можно использовать use в зависимости от условий (темная или светлая тема).
  2. Нет необходимости в явных потребителях контекста. Вместо того чтобы использовать компоненты-контекстные потребители (Context.Consumer), теперь можно просто вызвать use для получения значения контекста прямо в компоненте, даже в условных выражениях. Также, как и useContext, use находит ближайший провайдер контекста, который находится выше по дереву компонентов.

Серверные компоненты

Server Components в React 19 – новый способ рендеринга компонентов: рендеринг происходит заранее, либо один раз во время сборки, либо при каждом запросе на сервере, который отделен от клиентской части приложения. Похожим образом реализован серверный рендеринг в Next.js.

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

Раньше для получения статических данных, например, из CMS (системы управления контентом), часто использовали хук useEffect. Подобный код выполнялся после первого рендеринга страницы:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Проблема в том, что при этом:

  1. Клиент загружает лишние библиотеки (например, 75 КБ для работы с Markdown и его очистки).
  2. Данные загружаются после первого рендеринга страницы, что делает интерфейс медленнее.

Теперь все это можно загрузить сразу на сервере во время рендеринга, и клиенту не нужно ждать второй запрос или загружать лишние библиотеки:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Серверные действия

Server Actions – это новая функция в React, позволяющая компонентам на клиенте вызывать асинхронные функции, выполняемые на сервере. Она создает связь между клиентом и сервером с помощью директивы use server. Это своего рода туннель, через который клиент может отправлять данные серверу для обработки.

Server Actions создаются в Server Components и могут передаваться в компоненты клиента как свойства (пропсы) или импортироваться и использоваться напрямую в Client Components.

Директива use server не указывает, что это компонент сервера, а создает связь между сервером и клиентом. Подобно тому, как use client говорит React отправлять JavaScript-код на клиент, use server создает «туннель», через который клиент может отправлять данные на сервер для обработки.

Допустим, у нас есть серверный компонент для создания заметок в базе данных. Этот компонент передает действие на клиент для выполнения по нажатию кнопки:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Когда React рендерит компонент EmptyNote, он создает ссылку на функцию createNoteAction и передает ее в клиентский компонент Button. Когда пользователь нажимает кнопку, React отправляет запрос на сервер для выполнения этой функции. Клиентский компонент выглядит так:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Также можно вынести серверное действие в отдельный файл и импортировать его:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Клиентский код:

⚛️🔄 Улучшенная обработка асинхронных операций в React 19

Преимущества Server Actions:

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

React 19 привносит революционные изменения в мир фронтенд-разработки. Если вы хотите быть на гребне волны и освоить не только новые возможности React, но и фундаментальные основы современного веба, обратите внимание на курс Frontend Basic от Proglib Academy. Вот что вы получите:

  • Понимание принципов работы современного веба
  • Практический опыт создания интернет-магазина с нуля
  • Знания, необходимые для работы с новейшими технологиями, включая React
  • Возможность быстро адаптироваться к изменениям в мире фронтенд-разработки

Источники

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ