Найти тему
SimbirSoft

React: новинки 18 версии

Оглавление

Мы долго этого ждали, вокруг предстоящего релиза ходили слухи и домыслы, было заявлено много фич, напряжение нарастало… И вот наша любимая библиотека стала совсем взрослой! Весной разработчики React выкатили 18 версию.

Рассказываем о тех новшествах, которые попали в новою версию, и скорее всего, станут must have для рядового разработчика в ближайшее время. А также кратко затронем фичи, предназначенные для разработки сторонних библиотек.

Заострять внимание на улучшениях, касающихся SSR, не будем, это тема отдельной статьи. Подробнее можно почитать здесь.

Если вы уже пишете на React или расширяете кругозор в разработке — этот материал для вас.

Батчинг внутри асинхронных операций

Батчинг (batching — «дозирование, пакетирование») — это компоновка многочисленных обновлений состояния в один ре-рендер приложения для улучшения его производительности.

До 18 версии батчинг уже работал, но только в синхронном коде.

-2

Раньше под капотом React со знанием дела копил все изменения состояния, и, когда наступал подходящий момент, применял их сразу пачкой. Благодаря этому мы не тревожили лишний раз «дорогостоящий» DOM. Но это чудо инженерной мысли не работало внутри асинхронных операций. В новой версии это исправили, и по умолчанию батчинг теперь работает везде без исключений.

-3

Но если вдруг вам потребуется вернуть старое поведение, это легко сделать. Нужно всего лишь обернуть конкретное изменение состояния в функцию flushSync (она импортируется именно из react-dom, не из react). Это может потребоваться в особо редких кейсах, к примеру, если остро необходимо получить данные напрямую из DOM после изменения конкретной части состояния.

-4

Конкурентный режим

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

Преимущества конкурентного режима перед стандартным синхронным очевидны.

Для примера представим ситуацию, когда на странице есть список с большим количеством данных и инпут ввода для фильтрации этого списка. Фильтрация происходит на каждый ввод символа. На мощном железе все будет хорошо, но если у пользователя в распоряжении старый аппарат или мобильное устройство, тогда быть беде. При отрисовке списка инпут будет тормозить, и пользовательское взаимодействие с приложением будет заблокировано. Данную ситуацию можно смоделировать, замедлив вручную работу процессора в dev tools (вкладка performance).

И здесь нам на помощь приходят два новых хука — useTransition и
useDefferedValue
. С их помощью мы можем подсказывать React, какие изменения для нас важны прямо сейчас, а какие можно немного отложить и выполнить, как только представится возможность. То есть React сам ищет оптимальный момент, когда нужно применить отложенные изменения. И надо сказать, у него хорошо это получается.

Оба хука работают схожим образом, но все-таки у них есть отличия.

useTransition() — ничего не принимает и возвращает кортеж из двух элементов — флаг isPending и функцию startTransition. Данный хук позволяет не отображать состояние загрузки, когда контент обновляется перед переходом к следующему экрану. Теперь нам нужно лишь обернуть в эту функцию изменение стейта, которое мы хотим сделать отложенным. С помощью isPending мы сможем отследить, ожидаем ли в данный момент окончание перехода к следующему экрану (то есть когда рендер разбит на мелкие части, между которыми могут вставать другие, более приоритетные события). В данном случае флаг будет в значении true, и можно подсказать пользователю, что интерфейс загружается, например, с помощью прозрачности.

-5

Если на вашем проекте все еще используются классовые компоненты, а не хуки, то спешим вас обрадовать — разработчики React предоставили метод startTransition и для классовых компонентов.

useDefferedValue() принимает значение, пересчет которого мы хотим сделать отложенным, и возвращает клон этого значения. Принцип работы очень похож на debounce, но имеет ряд преимуществ в сравнении с последним. Он будет работать быстрее, так как «подкапотная» логика работы хука довольно неплохо продумана и оптимизирована (можно изучить исходники на github для более предметного изучения), не блокирует UI, не имеет фиксированной задержки.

-6

Два вышеописанных хука взаимозаменяемы, и их не стоит использовать вместе. Эффект от их применения, можно сказать, идентичен. Когда имеет место тяжелый ре-рендер, на который вы не можете повлиять напрямую через работу с состоянием (сторонние библиотеки), отлично подойдет useDefferedValue. В остальных случаях рекомендуется использовать useTransition.

На момент выхода данной статьи команда React уже готовит большую инструкцию по максимальному и наиболее эффективному использованию всех преимуществ конкурентного режима.

Разницу в работе прерываемого и обычного рендеринга можно посмотреть в dev tools (performance => кнопка Record).

Обычный рендеринг:

-7

Прерываемый:

-8

offScreen API

Киллер-фича новой версии, которую все ждали, наверное, больше всего. Увы, на момент выхода статьи ее пока нет, но она должна появиться в минорном релизе. Заявленный функционал должен будет уметь скрывать компонент, не размонтируя его. Тем самым будет сохраняться последнее состояние компонента. Может стать очень удобным при переходе между вкладками, табами и т.д.

Возможность вернуть undefined из компонента

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

Апгрейд использования памяти

Теперь при размонтировании компонента очищается больше внутренних полей, что позволяет сделать незафиксированные утечки памяти менее значительными.

Важные обновления для разработчиков библиотек:

  1. useId() — хук, генерирующий уникальное значение. Полезен при использовании SSR, для связки разных частей приложения, отрендеренных на сервере и на клиенте.
  2. useSyncExternalStore — хук, для библиотек, работающих с состоянием.
  3. useInsertionEffect — хук, для библиотек работающих со стилями css in js.

Как перейти на React 18:

🔹 Обновиться до 18 версии.

🔹 Перевести приложение на новый root Api.

-9

🔹 Убрать из кода устаревшие методы жизненного цикла. Здесь может помочь режим React.StrictMode, который подскажет, что уже не актуально и лучше убрать.

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

🔹 Подождать, пока обновятся сторонние библиотеки, если вы их используете, и начнут поддерживать конкурентный режим. На данный момент большинство сторонних библиотек не совместимы с новым режимом.

Заключение

Наверное, самое важное обновление React 18 заключается в возможности прерываемого рендеринга. Это положительно влияет на производительность, удобство разработки и в конечном счете на пользовательский опыт. Поэтому с большой вероятностью описанные нововведения в ближайшее время войдут в постоянную практику на проектах.

Надеемся, что смогли пролить свет на некоторые вопросы, связанные с выходом новой версии React и данный материал был вам полезен.

__________________________________________________________________________________________

Предлагаем подписаться на наши социальные сети и блог, чтобы не пропустить интересные события и материалы по frontend-разработке:
Telegram:
https://t.me/simbirsoft_dev
ВКонтакте:
https://vk.com/simbirsoft_team
Яндекс Дзен:
https://zen.yandex.ru/simbirsoft
Habr:
https://habr.com/ru/company/simbirsoft/blog/
YouTube:
https://www.youtube.com/user/SimbirSoft/videos