🚀 Новые возможности React 19: конец эры повторных рендерингов
Новый компилятор React 19 обещает существенное повышение производительности, что станет настоящим прорывом для разработчиков. Но это лишь верхушка айсберга. В этой статье мы не только разберемся, как работает компилятор, но и погрузимся в мир других новейших возможностей React 19.
Привет, друзья! Я Кирилл Мыльников, фронтенд-разработчик в компании Usetech. Сегодня хочу поделиться о новейших функциях в React 19. Давайте вместе применим их в практике, разберем новшества и возможности на примерах, чтобы узнать, как они могут улучшить нашу разработку! Готовы к погружению?
Компилятор React
Это новейшее дополнение к React — компилятор, заменяющий транспилятор, применяется в React 19. В React 18 и ниже использовался транспилятор, который при изменении состояния перерисовывал весь компонент. В отличие от него, компилятор возвращает мемоизированный код, устраняя ненужный повторный рендеринг и улучшая производительность приложений React. Давайте запустим код в обеих версиях и изучим разницу в поведении компонентов при повторной визуализации.
Пример
Представленный выше код представляет собой приложение-счетчик, которое увеличивает и уменьшает счетчик при нажатии кнопки. В нем реализована функция TimeToRender, которая замеряет время, требуемое для рендеринга компонента при каждом обновлении.
На иллюстрации ниже показан процесс рендеринга компонента в компиляторе, а также время, необходимое для его повторного рендеринга.
На изображении ниже показано время, требуемое для каждого повторного рендеринга всего компонента при использовании транспилятора.
На представленном изображении выше мы видим, что транспилятор выполняет несколько повторных рендеров, при этом время каждого последующего рендера сокращается после каждого щелчка, в то время как компилятор выполняет рендер только один раз.
Ранее мы использовали хуки memo, useMemo() и useCallback() для достижения подобного эффекта, что делает эти хуки устаревшими. Новый подход позволяет нам писать более чистый и компактный код.
Хуки — это одна из наиболее популярных особенностей React. Они обеспечивают удобное управление состоянием и жизненным циклом компонентов. В React уже встроены некоторые хуки, а также предоставляется возможность создания собственных пользовательских хуков.
React 19 внедрил поддержку использования async функций в переходах для управления изменениями состояния, которые могут повлечь изменения пользовательского интерфейса. Существует возможность использовать хук useTransition для обновления статуса состояния и автоматического отображения процесса ожидания.
Это гарантирует плавную обработку обновлений при инициации пользователем. Кроме того, интерфейс будет точно отображать текущее состояние асинхронной функции. Давайте посмотрим на пример кода.
Приведенный ниже код представляет собой приложение, которое добавляет буквы алфавита в список. При нажатии кнопки "Добавить" происходит ожидание 4 секунды перед добавлением новой буквы в список. Мы можем автоматически управлять состоянием ожидания с помощью функции startTransition().
На изображении ниже показано, что состояние ожидания остается равным true до того момента, пока буква алфавита не будет добавлена в список через 4 секунды.
Это происходит в отличие от предыдущих версий, где нам приходилось вручную управлять состоянием ожидания, используя функцию setIsPendingding для установки состояния в значение true или false.
useActionState
Хук useActionState применяется для управления изменениями состояния в пользовательском интерфейсе, аналогично хуку useTransition. Отличие между ними заключается в том, что useActionState позволяет установить состояния error, action и pending в одной строке кода, вместо нескольких строк, как показано выше. Кроме того, хук useTransition обрабатывает только состояние ожидания.
Путем использования хука useActionState мы можем переписать предыдущий код более компактно, что приведет к уменьшению количества строк кода.
В представленном выше коде хук useActionState используется для автоматической обработки состояний error, submitAction и isPending без явного определения через useState или useTransition для состояний, ожидающих обновления, как мы делали ранее.
Хук useFormStatus предоставляет доступ к информации о состоянии отправленной формы. С его помощью можно получить доступ к состоянию формы и определить, находится ли она в режиме ожидания или нет.
Ниже приведен пример кода, в котором использован хук useFormStatus для доступа к состоянию ожидания формы.
Ранее для доступа к состоянию ожидания мы передавали это состояние как пропс. В приведенном ниже примере кода мы передали состояние isPending как пропс в функцию CustomButton, чтобы иметь к нему доступ в операторе return.
useOptimistic
Этот хук позволяет нам обновлять пользовательский интерфейс немедленно при изменении определенного состояния, даже без ожидания завершения асинхронного действия. Например, в чат-приложениях, когда сообщение отправляется, оно мгновенно отображается в интерфейсе до его фактической отправки получателю. Часто добавляются индикаторы, такие как галочки, чтобы указать, когда сообщение будет полностью доставлено.
В приведенном ниже коде показано приложение для списка задач, где при добавлении новой задачи она проходит через асинхронную функцию и затем обновляется в пользовательском интерфейсе через 4 секунды. Мы используем хук useOptimistic для мгновенного отображения добавленной задачи в интерфейсе до завершения 4-секундного временного интервала.
На данном изображении демонстрируется мгновенное обновление пользовательского интерфейса. Через 4 секунды отображаемая задача заменяется на актуальную задачу с сервера.
Ранее для решения этой задачи мы использовали хук useState для управления оптимистичным отображением задач и их дальнейшего обновления с фактическими данными.
Вышеприведенный код использует хук useState для добавления оптимистичных обновлений интерфейса в состояние optimisticTasks, а также функцию-сеттер setOptimisticTasks для обновления этого состояния.
API use позволяет использовать промисы и async-await. Он принимает только промис, а не функцию, и обновляет пользовательский интерфейс после завершения промиса. Вы можете вызывать этот API внутри операторов if и циклов.
В приведенном примере кода содержатся две асинхронные функции, которые имитируют задержку при получении данных, как это обычно происходит при отправке запросов на сервер. Первая функция возвращает список авторов после задержки в 4 секунды, а вторая – список блогов после задержки в 2 секунды. Затем пользовательский интерфейс обновляется этими значениями.
На данном изображении демонстрируется, что пользовательский интерфейс обновляется только после того, как все промисы загрузились.
Улучшение передачи ref в пропсах
В React 19 теперь можно передавать ref как обычное свойство объекта, а не обязательно использовать forwardRef для передачи ref компоненту. Это позволяет сохранять значения ref между рендерингами и избегать дополнительных перерисовок компонента.
Вот пример новой реализации передачи ref как обычного свойства объекта:
Ранее мы использовали forwardRef для определения компонента OldRef. Этот метод позволяет компоненту получить доступ к ref, передаваемому ему. Рассмотрим пример реализации:
Поддержка метаданных документа
React 19 теперь поддерживает рендеринг тегов метаданных прямо в компоненте без использования сторонних библиотек, таких как react-helmet. В приведенном ниже коде мы обновляем элементы title и meta непосредственно в компоненте App:
Вот пример того, как мы делали это в более ранних версиях с использованием библиотеки react-helmet. В этом примере мы обновляли элементы title и meta через react-helmet:
В приведенном выше коде для установки элементов title и meta мы использовали компонент Helmet из библиотеки react-helmet.
Улучшенные отчеты об ошибках
Ошибки в новой версии React 19 стали выглядеть менее многословно и более читаемо. Теперь вместо дублирования ошибок в консоли React 19 пытается предоставить одну ошибку с полной информацией о проблеме. На изображении ниже показана ошибка, возникшая в компоненте ErrorComponent в React 18.
Вот изображение, демонстрирующее ту же ошибку, как и в React 19, но представленную в отчете React 18.
Заключение
React 19 представляет захватывающие новые функции, которые значительно улучшают опыт разработчиков. Мы осмыслили такие новые функции, как компилятор, способный решать проблемы повторного рендеринга, новые хуки для улучшения пользовательского опыта, а также улучшенные отчеты об ошибках, предоставляющие более лаконичные сообщения об ошибках.
Комментарии
Статья топ, на мой взгляд. Отдельное спасибо за гифки!