React Conf 2024. React v19
- пятница, 17 мая 2024 г. в 00:00:09
Temp UPD: прямо сейчас проходит второй день React Conf.
Несколько часов назад завершился первый день Конференции React.js. Долгожданной конференции спустя почти 3 года после предыдущей. Не менее долгожданны и обновления реакта. И именно с них была начата конференция, им и будет посвящена статья. И да, как вы увидели из превью — 19 версия перешла в статус release candidate. Полноценный же релиз нам обещают в течении двух недель.
В целом, мне как next.js разработчику большая часть была знакома. Десятки статей на хабре уже рассказали о практически каждой части этого обновления, частично их касался и я рассказывая об обновлениях внесённых в next.js.
Можно сказать, что главным направлениям этого обновления было достижение «Высокого UX при высоком DX». Максимальная производительность при максимально простом коде. При этом в части обновлений практически не было упоминаний серверных компонент, лишь косвенно. И так, перейдём к самой конференции.
Как обычно в подобных конференциях всё начинается с описания роста. Загрузки реакта достигнули Одного Миллиарда в год. Сам рост инструмента непременно связан с ростом сообщества. Поэтому также показана и статистика stackoverflow 40% разработчиков используют react при веб разработке, 36% его изучает.
Также из интересного функционал React‑а стал в большей степени возможен только в рамках фреймворков и поэтому теперь React.js начал рекомендовать конкретные. На слайде были показаны remix, redwoodjs, next.js и expo. Из интересного — в этом списке нет react router.
Да! React Router теперь можно вносить в этот список. О нём был первый доклад конференции от Раяна Флоренса. Теперь с react router можно делать не только SPA, но и SSR, и SSG. Возможно это сейчас в связке с Vite. Доступны хуки для работы с данными и серверные компоненты.
Но пока давайте вернёмся к изменениям React.js. Следом описывалась проблема согласования элементов и расширения приложения. JSX решил проблему согласования элементов в разработке UI. Затем добавили Suspense, который решил проблему согласования элементов при загрузке элементов (что делать при загрузке и что в это время показывать пользователю).
В React 19 также были добавлены:
Серверные компоненты. Среди прочего такие компоненты могут решить проблему загрузки данных и их дальнейшей передачи в компоненты (с помощью привычных props);
Встраивание metadata. Метатеги можно встраивать в любом месте. React сам добавит их в нужное место и оставит только в единственном экземпляре.
Методы предзагрузки. Помимо добавления тегов вручную, также были добавлены методы для предзагрузки ссылок — preinit, preload, prefetchDNS и preconnect. Также в документации описаны методы preloadModule и preinitModule, но они по какой‑то причине не были показаны на конференции.
Встраивание стилей. Похожая с метаданными работа будет выполняться и для стилей. Однако здесь добавляется опция приоритизации — в зависимости от неё будет определяться какие стили важнее (и соответственно будут стоять ниже по ДОМ‑у).
Загрузку стилей компонента теперь отслеживает и suspense. То есть можно отображать лоадер не только пока рендерится компонент, но и пока готовятся его специфичные стили.
С появлением серверных компонент React взял на себя больше ответственности в части серверного рендеринга, как следствие, на гидрации ложится ещё больше логики и возможных проблем. Команда React.js улучшила ошибки гидрации.
Помимо значительных изменений в работе с построением реального дерева, в React.js обновилась логика взаимодействия с формами. В первую очередь в react‑dom был включен компонент form, что означает значительные изменения над элементом. И в первую очередь это изменение касается изменения атрибута «action» — в альтернативу отправке формы посредством onSubmit или нативного атрибута.
Добавление action само по себе выглядит также как onSubmit, но вместо event-а принимает сразу FormData.
Также для полей и кнопок формы добавлен проп formAction, который работает идентичным образом.
Пожалуй базовым преимуществом использования action вместо onSubmit является то, что при клиентских действиях, если пользователь вызовет отправку формы сразу (ещё до загрузки логики формы) — её отправка будет отложена и выполнится как только логика будет готова. В серверных же действиях отправка произойдёт сразу, т.к. не требует клиентского js.
Но, помимо базовой разницы есть и значительные изменения во взаимодействии с отправкой форм — это новые хуки. useOptimistic, useFormStatus и useActionState.
Примерами работы с ними поделился Сэм Селикофф (Sam Selikoff) на докладе «React unpacked: A Roadmap to React 19». Например так выглядит замена onSubmit на action + useActionState:
Затем можно добавить оптимистичный рендер:
И вновь вернёмся с доклада к ключевым изменениям. Следом было показано относительно небольшое изменения, но очень и очень ценное. В React.js 19 передать ref в функциональный компонент можно как props. Сразу. Без forwardRef.
Также при передаче ref в компоненты можно вернуть колбек на unmount.
Заключительным ключевым изменением стал React Compiler. Продвинутый лоадер с мемоизацией из коробки. Вместе с ним React будет автоматически настраивать мемоизацию в приложении. Подробнее рассказала Лаурен Тан (Lauren Tan) в докладе «React Compiler Case Studies».
Так вот, чтобы понять как настроить мемоизацию React анализирует связи от места вызывающего ререндер до конечных точек:
Исходя из этих связей компилятор может представить себе полный граф зависимостей:
И дальше, в зависимости от этих связей, устанавливать мемоизацию с нужными зависимостями. В данном случае так как songs не меняется — filteredSongs должны остаться прежними (будут мемоизированы с зависимостью от songs), а если изменили song посредством setSong должен быть перерендерен NowPlaying (будет мемоизирован с зависомостью от song).
«Максимальная производительность при максимально простом коде».
Отличное решение, однако интересно посмотреть как будут на практике устанавливаться мемоизации — где их стоит прописывать разработчикам, а где стоит не усложнять и оставить эту логику компилятору.
Установить компилятор можно уже сейчас на все основные фреймворки и системы сборки, поддерживающие babel. Он уже используется в instagram, facebook и bluesky (компания в которой сейчас работает Дэн Абрамов).
Также, чтобы повысить надёжность и качество компиляции можно установить eslint плагин, который подскажет все проблемы с оптимизацией кода.. В целом сам плагин можно использовать и независимо от компилятора.
npm install eslint-plugin-react-compiler
Также можно воспользовать командной утилитой, которая проверит приложение на возможность оптимизации компилятором
npx react-compiler-healthcheck
Ещё одним нововведением поделилась Лидия Халли (Lydia Hallie) — функция use. Да, это не ошибка — это не хук.
Ключевым отличием use
от хуков является то, что use
можно использовать внутри условий
Сам use может принимать либо promise, либо context. Сложно представить ситуацию, в которой нельзя быть уверенным что передастся аргументом в use - promise или контекст и почему попросту не сделали две самостоятельные функции.
В завершении отмечу потрясающие доклады, презентации, примеры и выступления в целом. Команда React.js смогла действительно показать возможности всех улучшений (к сожалению команда next.js справилась с этой задачей сильно хуже). Также из приятной разницы отмечу, что команда React.js отказалась вносить в ядро перезапись fetch API и откатила уже готовые изменения.
Общий список изменений выглядит следующим образом:
UPD: Кажется здесь можно оставить немного рекламы.
Если вы пользуетесь next.js — можете посмотреть на решения nimpl.tech, возможно некоторые из них вы найдёте полезными (как например геттер getPathname для серверных компонент или пакет для конфигурации config настроенный под все окружения next.js)