"React 19 RC". Источник: React Conf 2024
"React 19 RC". Источник: React Conf 2024

Несколько часов назад завершился первый день Конференции React.js. Долгожданной конференции спустя почти 3 года после предыдущей. Не менее долгожданны и обновления реакта. И именно с них была начата конференция, им и будет посвящена статья. И да, как вы увидели из превью — 19 версия перешла в статус release candidate. Полноценный же релиз нам обещают в течении двух недель.

В целом, мне как next.js разработчику большая часть была знакома. Десятки статей на хабре уже рассказали о практически каждой части этого обновления, частично их касался и я рассказывая об обновлениях внесённых в next.js.

Можно сказать, что главным направлениям этого обновления было достижение «Высокого UX при высоком DX». Максимальная производительность при максимально простом коде. При этом в части обновлений практически не было упоминаний серверных компонент, лишь косвенно. И так, перейдём к самой конференции.

Как обычно в подобных конференциях всё начинается с описания роста. Загрузки реакта достигнули Одного Миллиарда в год. Сам рост инструмента непременно связан с ростом сообщества. Поэтому также показана и статистика stackoverflow 40% разработчиков используют react при веб разработке, 36% его изучает.

Один миллиард загрузок React.js в год. Источник: React Conf 2024
Один миллиард загрузок React.js в год. Источник: React Conf 2024

Также из интересного функционал React‑а стал в большей степени возможен только в рамках фреймворков и поэтому теперь React.js начал рекомендовать конкретные. На слайде были показаны remix, redwoodjs, next.js и expo. Из интересного — в этом списке нет react router.

Да! React Router теперь можно вносить в этот список. О нём был первый доклад конференции от Раяна Флоренса. Теперь с react router можно делать не только SPA, но и SSR, и SSG. Возможно это сейчас в связке с Vite. Доступны хуки для работы с данными и серверные компоненты.

Пример на React Router v7. Источник: React Conf 2024
Пример на React Router v7. Источник: React Conf 2024

Но пока давайте вернёмся к изменениям React.js. Следом описывалась проблема согласования элементов и расширения приложения. JSX решил проблему согласования элементов в разработке UI. Затем добавили Suspense, который решил проблему согласования элементов при загрузке элементов (что делать при загрузке и что в это время показывать пользователю).

В React 19 также были добавлены:

  • Серверные компоненты. Среди прочего такие компоненты могут решить проблему загрузки данных и их дальнейшей передачи в компоненты (с помощью привычных props);

  • Встраивание metadata. Метатеги можно встраивать в любом месте. React сам добавит их в нужное место и оставит только в единственном экземпляре.

Встраивание метаданных в React 19. Источник: React Conf 2024
Встраивание метаданных в React 19. Источник: React Conf 2024
  • Методы предзагрузки. Помимо добавления тегов вручную, также были добавлены методы для предзагрузки ссылок — preinit, preload, prefetchDNS и preconnect. Также в документации описаны методы preloadModule и preinitModule, но они по какой‑то причине не были показаны на конференции.

Методы предзагрузки в React 19. Источник: React Conf 2024
Методы предзагрузки в React 19. Источник: React Conf 2024
  • Встраивание стилей. Похожая с метаданными работа будет выполняться и для стилей. Однако здесь добавляется опция приоритизации — в зависимости от неё будет определяться какие стили важнее (и соответственно будут стоять ниже по ДОМ‑у).

Встраивание стилей в React 19. Источник: React Conf 2024
Встраивание стилей в React 19. Источник: React Conf 2024

Загрузку стилей компонента теперь отслеживает и suspense. То есть можно отображать лоадер не только пока рендерится компонент, но и пока готовятся его специфичные стили.

"Suspense для css". Источник: React Conf 2024
"Suspense для css". Источник: React Conf 2024

С появлением серверных компонент React взял на себя больше ответственности в части серверного рендеринга, как следствие, на гидрации ложится ещё больше логики и возможных проблем. Команда React.js улучшила ошибки гидрации.

Сравнение ошибок гидрации в React18 и React 19. Источник: React Conf 2024
Сравнение ошибок гидрации в React18 и React 19. Источник: React Conf 2024

Помимо значительных изменений в работе с построением реального дерева, в React.js обновилась логика взаимодействия с формами. В первую очередь в react‑dom был включен компонент form, что означает значительные изменения над элементом. И в первую очередь это изменение касается изменения атрибута «action» — в альтернативу отправке формы посредством onSubmit или нативного атрибута.

Плюсы и минусы атрибута action и onSubmit в React. Источник: React Conf 2024
Плюсы и минусы атрибута action и onSubmit в React. Источник: React Conf 2024

Добавление action само по себе выглядит также как onSubmit, но вместо event-а принимает сразу FormData.

Использование action в React 19. Источник: React Conf 2024
Использование action в React 19. Источник: React Conf 2024

Также для полей и кнопок формы добавлен проп formAction, который работает идентичным образом.

Пожалуй базовым преимуществом использования action вместо onSubmit является то, что при клиентских действиях, если пользователь вызовет отправку формы сразу (ещё до загрузки логики формы) — её отправка будет отложена и выполнится как только логика будет готова. В серверных же действиях отправка произойдёт сразу, т.к. не требует клиентского js.

Но, помимо базовой разницы есть и значительные изменения во взаимодействии с отправкой форм — это новые хуки. useOptimistic, useFormStatus и useActionState.

Примерами работы с ними поделился Сэм Селикофф (Sam Selikoff) на докладе «React unpacked: A Roadmap to React 19». Например так выглядит замена onSubmit на action + useActionState:

Использование useActionState в React 19. Источник: React Conf 2024
Использование useActionState в React 19. Источник: React Conf 2024

Затем можно добавить оптимистичный рендер:

Использование useOptimistic в React 19. Источник: React Conf 2024
Использование useOptimistic в React 19. Источник: React Conf 2024

И вновь вернёмся с доклада к ключевым изменениям. Следом было показано относительно небольшое изменения, но очень и очень ценное. В React.js 19 передать ref в функциональный компонент можно как props. Сразу. Без forwardRef.

"Never use forwardRef again". Источник: React Conf 2024
"Never use forwardRef again". Источник: React Conf 2024

Также при передаче ref в компоненты можно вернуть колбек на unmount.

Callback функция на unmount компонента в React 19. Источник: React Conf 2024
Callback функция на unmount компонента в React 19. Источник: React Conf 2024

Заключительным ключевым изменением стал React Compiler. Продвинутый лоадер с мемоизацией из коробки. Вместе с ним React будет автоматически настраивать мемоизацию в приложении. Подробнее рассказала Лаурен Тан (Lauren Tan) в докладе «React Compiler Case Studies».

Так вот, чтобы понять как настроить мемоизацию React анализирует связи от места вызывающего ререндер до конечных точек:

Связи для React compiler. Источник: React Conf 2024
Связи для React compiler. Источник: React Conf 2024

Исходя из этих связей компилятор может представить себе полный граф зависимостей:

Граф связей для React Compiler. Источник: React Conf 2024
Граф связей для React Compiler. Источник: React Conf 2024

И дальше, в зависимости от этих связей, устанавливать мемоизацию с нужными зависимостями. В данном случае так как songs не меняется — filteredSongs должны остаться прежними (будут мемоизированы с зависимостью от songs), а если изменили song посредством setSong должен быть перерендерен NowPlaying (будет мемоизирован с зависомостью от song).

Зависимости при ререндерах для React Compiler. Источник: React Conf 2024
Зависимости при ререндерах для React Compiler. Источник: React Conf 2024

«Максимальная производительность при максимально простом коде».

Отличное решение, однако интересно посмотреть как будут на практике устанавливаться мемоизации — где их стоит прописывать разработчикам, а где стоит не усложнять и оставить эту логику компилятору.

Установить компилятор можно уже сейчас на все основные фреймворки и системы сборки, поддерживающие babel. Он уже используется в instagram, facebook и bluesky (компания в которой сейчас работает Дэн Абрамов).

Также, чтобы повысить надёжность и качество компиляции можно установить eslint плагин, который подскажет все проблемы с оптимизацией кода.. В целом сам плагин можно использовать и независимо от компилятора.

npm install eslint-plugin-react-compiler

Также можно воспользовать командной утилитой, которая проверит приложение на возможность оптимизации компилятором

npx react-compiler-healthcheck

Ещё одним нововведением поделилась Лидия Халли (Lydia Hallie) — функция use. Да, это не ошибка — это не хук.

use в React 19. Источник: React Conf 2024
use в React 19. Источник: React Conf 2024

Ключевым отличием use от хуков является то, что use можно использовать внутри условий

Использование use в React 19. Источник: React Conf 2024
Использование use в React 19. Источник: React Conf 2024

Сам use может принимать либо promise, либо context. Сложно представить ситуацию, в которой нельзя быть уверенным что передастся аргументом в use - promise или контекст и почему попросту не сделали две самостоятельные функции.

В завершении отмечу потрясающие доклады, презентации, примеры и выступления в целом. Команда React.js смогла действительно показать возможности всех улучшений (к сожалению команда next.js справилась с этой задачей сильно хуже). Также из приятной разницы отмечу, что команда React.js отказалась вносить в ядро перезапись fetch API и откатила уже готовые изменения.

Общий список изменений выглядит следующим образом:

Обновления в React 19. Источник: React Conf 2024
Обновления в React 19. Источник: React Conf 2024

UPD: Кажется здесь можно оставить немного рекламы.

Если вы пользуетесь next.js — можете посмотреть на решения nimpl.tech, возможно некоторые из них вы найдёте полезными (как например геттер getPathname для серверных компонент или пакет для конфигурации config настроенный под все окружения next.js)

UPD2: здесь всё ещё есть входы, поэтому оставлю ещё обновление.

Только что поставил PR на добавление функционала getPageContext в next.js (читателям вне next.js - огромная боль работа с контекстами в серверных компонентах [потому что их там попросту нет и нет никаких альтернатив]). Поставьте реакцию, если вам знакома эта боль.

Комментарии (10)


  1. slavb18
    16.05.2024 08:28

    Спасибо! Благодаря nextjs и react 19 (server components, server actions, form) становится проще писать приложения.


    1. Vordgi Автор
      16.05.2024 08:28

      А что в изменениях next.js нравится и упростило написание кода (именно next.js, т.е. навигация в app router, новые роуты и абстракции, кеширование и т.п.)?

      Всё ещё испытываю очень спорные эмоции и хочу понять в чём улучшило жизнь другим (или ухудшило, тоже очень интересно, особенно если решу писать по нему ещё статьи).

      (О своих итогах писал в первую очередь в статье про App Router и статье про кеширование в next.js)


  1. diXrom
    16.05.2024 08:28

    Пакет для конфигурации config настроенный под все окружения next.js

    Можете поподробнее рассказать об этом?


    1. Vordgi Автор
      16.05.2024 08:28

      Можно сказать, что nextjs исполняется в четырёх средах: сервер, клиент, edge и сборка. Сам он для конфигурации предлагает использовать env файлы и два вида переменок - серверные и публичные (начинаются с NEXT_PUBLIC_ и будут встроены в код во время сборки).

      Для edge рантайма и клиента приходится использовать публичные переменные. А это в свою очередь означает, что приложение будет полностью зафиксировано под окружение в момент сборки.

      Пакет же даёт возможность настроить файлы конфигураций в стиле, схожем с пакетом config, под каждую среду и использовать их в нужных местах в нужном окружении.

      https://github.com/vordgi/nimpl-config/tree/main/example/config

      В общем интересный эксперимент как можно иначе конфигурировать fullstack приложение.

      (Думаю [когда-нибудь, [надеюсь [и мне хочется верить]]], что я допишу по нему статью)


      1. diXrom
        16.05.2024 08:28

        а как к ним обращаться в коде для рантайма, так же как и раньше process.env.NEXT_PUBLIC_ ?


        1. Vordgi Автор
          16.05.2024 08:28

          После настройки: const config = useRuntimeConfig();

          Есть вполне достаточный пример - https://github.com/vordgi/nimpl-config/blob/main/example. Ну и дока, конечно, тоже есть - https://nimpl.tech/config/usage)