Основные изменения React 18
Привет, меня зовут Кристина, я фронтенд-разработчик в Домклик. Хочу рассказать немного про основные изменения React 18.

- Новые возможности ( useId , useDeferredValue , useSyncExternalStore , useInsertionEffect ).
- Переходы ( startTransition , useTransition ).
- Suspense на сервере.
- Конкурентный рендеринг.
- Автоматический батчинг.
- ReactDOM.render ⇒ ReactDOM.createRoot
- ReactDOM.hydrate ⇒ ReactDOM.hydrateRoot
- ReactDOM.unmountComponentAtNode
- ReactDOM.renderSubtreeIntoContainer
- ReactDOMServer.renderToNodeStream
- npm install react react-dom или yarn add react react-dom .
- Так как ReactDOM.render устарел, необходимо с помощью ReactDOM.createRoot создать root и отрендерить, применяя его. Без этого новые возможности React 18 будут недоступны.
import ReactDOM from 'react-dom'; import App from 'App'; const container = document.getElementById('app'); const root = ReactDOM.createRoot(container); root.render();
Конкурентный рендеринг (Concurrency)
Что такое конкурентность? Например, вам нужно позвонить Алисе и Бобу. В неконкурентном режиме вы сначала позвоните Алисе, и только после завершения разговора с ней позвоните Бобу. Если разговоры короткие, то всё в порядке, но если разговор с Алисой задержался, например из-за проблем на линии, то это может стать потерей времени.

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

Рендеринг можно прерывать, приостанавливать, возобновлять или прекращать. Это позволяет React быстро реагировать на взаимодействия с пользователем. До React 18 рендеринг представлял собой одну непрерывную синхронную транзакцию, и после начала её нельзя было прервать.
Автоматический батчинг (Automatic batching)
Что такое батчинг? Предлагаю рассмотреть ещё один пример из жизни. Допустим, вы решили приготовить салат. Составили список всех продуктов, которые вам нужно купить, идёте в магазин и покупаете всё за один раз — это батчинг.
Без батчинга вы начинаете готовить, потом оказывается, что у вас нет огурцов для салата, вы идёте в магазин, покупаете огурцы, возвращаетесь и продолжаете готовить, затем вы обнаруживаете, что у вас нет помидоров, вы идёте в магазин и… в этот момент вы уже выполнили свою дневную норму на фитнес-браслете.
В React батчинг помогает уменьшить количество повторных рендерингов, которые происходят при вызове setState .
setIsLoaded(true); setError(true); setModalStatus(‘error’);
В этом коде React будет заново рендерить после каждого из вызовов, но это не эффективно. Было бы лучше сначала записать все обновления состояния, а затем после них один раз отрендерить. Но как React может понять, что вы закончили обновлять состояния? А понять он может, например, с помощью обработчика событий:
// Такое поведение в React 17 и в React 18 function handleClick()
Повторный рендеринг произойдёт после того, как будет выполнена функция.
Рассмотрим ещё один пример:
setTimeout(() => < setIsLoaded(true); setError(true); setModalStatus(‘error’); >, 1000);
До React 18 повторный рендеринг происходил бы при каждом обновлении состояния. Но теперь все обновления будут автоматически батчиться внутри таймаутов, промисов или нативных обработчиков событий.
Переходы (Transitions)
Переходы можно использовать для обозначения срочных и несрочных обновлений. Например, при вводе текста в поле поиска появляется мигающий курсор, дающий визуальную обратную связь, и выполняется функция поиска данных. Визуальная обратная связь важнее для пользователя, а поиск менее важен и может быть помечен как несрочный. Такие несрочные обновления называются переходами (transitions). Проставляя их, вы даёте React знать, каким обновлениям отдавать приоритет. Это упрощает оптимизацию рендеринга.
Обновления можно пометить как несрочные с помощью startTransition :
import < startTransition >from 'react'; // Срочное обновление значения инпута setInputValue(value); // Несрочное обновления запроса поиска startTransition(() => < setSearchValue(value); >);
В чём отличие от setTimeout ?
- setTimeout имеет задержку в выполнении, а задержка startTransition зависит от устройства, на котором выполняется, и других срочных рендерингов.
- Обновления startTransition могут быть прерваны.
- Со startTransition можно отслеживать состояния ожидания с помощью нового хука useTransition .
function Counter() < // Состояние ожидания const [isPending, startTransition] = useTransition(); const [value, setValue] = useState(0); const handleClick = () => < startTransition(() => < setValue(c =>c + 1); >) > return ( <> < isPending && > > >); >
Suspense
В React 18 эта технология была архитектурно улучшена. Изменён рендеринг дочерних компонентов внутри Suspense. Также теперь есть возможность использования Suspense на сервере. Но что же это такое?
Представьте себе компонент, которому нужно выполнить асинхронную задачу, например, получение данных, прежде чем он сможет что-то отрендерить. Без Suspense такой компонент сохранял бы флаг isFetching / isLoading и в зависимости от него рендерил бы загрузчик, или скелет, или что-то ещё. А теперь с помощью Suspense компонент может дать понять, что он ещё «не готов», и приостановить рендеринг. В это время React пойдёт вверх по дереву до ближайшего Suspense, в котором будет установлен fallback, так называемый запасной вариант, который будет отображаться, пока компонент не будет «готов».
Строгий режим
Строгий режим в React 18 будет имитировать unmount и повторный mount компонента с его предыдущим состоянием, когда mount происходит первый раз. Это закладывает основу для многократного использования состояния в будущем, когда React может немедленно смонтировать предыдущий экран

Пожалуй это всё о чем я хотела рассказать в этой статье. Любые изменения ведут к новым возможностям. Удачи в обновлении!
React 18: новые хуки и как изменился рендеринг
Всё об обновлении React 18: автоматический батчинг, конкурентный режим, изменения в архитектуре рендеринга на стороне сервера и новые хуки.
В этом материале мы рассмотрим часть обновлений, которые для нас приготовил React 18 — разберем automatic batching, concurrent rendering, изменения в архитектуре приостановки рендеринга на стороне сервера и новые хуки.
К обновлениям добавлю примеры кода, и что нужно сделать, чтобы начать пользоваться новым функционалом.
Егор Половинкин
Frontend-разработчик IT-компании MediaSoft
Automatic batching
React 18 добавляет возможность автоматического батчинга обновления состояний для асинхронных операций. Например, promise, таймауты, fetch-запросы. Это положительно сказывается на производительности.
Батчингом в React называют процесс группировки нескольких вызовов обновления состояний в один этап ререндера. Другими словами, пакетная обработка.
Раньше группировка происходила только внутри обработчиков событий.
function App() < const [count, setCount] = useState(0); const [flag, setFlag] = useState(false); function handleClick() < // До React 18 следующие вызовы не батчились // Установка состояния происходит «после» события в колбэке асинхронного вызова fetchSomething().then(() => < setCount(c =>c + 1); // Спровоцирует ререндер setFlag(f => !f); // Спровоцирует ререндер >); // В React 18 fetchSomething().then(() => < setCount(c =>c + 1); // Не вызывает ререндер setFlag(f => !f); // Не вызывает ререндер // React будет вызывать ререндер только один раз, в конце >) > return ( >> ); >
Concurrent rendering и новые хуки
Concurrent rendering (конкурентный режим) предназначен для более плавной работы приложения на устройстве пользователя. Одна из областей применения — прерываемый рендеринг. Представьте, что пользователь вводит в строку поиска текст. Событие обновляет состояние компонента, и происходит рендер нового списка результатов. Во время этого процесса залипает ввод: браузер не может обновить введенный в поле текст, т.к. занимается рендером нового списка результатов. Конкурентный режим исправляет это ограничение и делает рендер прерываемым.
С новыми фичами конкурентного рендеринга были добавлены и новые API: переходы состояния (state transition), фичи задержки (Suspense) и новые хуки.
startTransition
Метод API добавлен для обновления состояния компонента, которое влечет за собой тяжелые вычисления. Например, фильтрация списка. Это позволяет значительно улучшить пользовательский ввод и отклик интерфейса, т.к. помечает тяжелые обновления компонента как «переходы» — transitions.
В API представлено в виде функции startTransition, в которую помещают обновления состояний, являющихся несрочными — non-urgent.
import < startTransition >from 'react'; // Срочное (urgent) обновление: отображаем введенный текст setInputValue(input); // Помечаем обновления состояний как переходы startTransition(() => < // Переход: фильтрация списка по введенному ключевому слову setSearchQuery(input); >);
startTransition полезен, если вы хотите сделать пользовательский ввод быстрым, не было фриза UI, а несрочные операции выполнялись на фоне.
useTransition
Помимо startTransition появился новый хук useTransition. Он позволяет узнать статус перехода:
import < useTransition >from 'react'; const [isPending, startTransition] = useTransition();
useDeferredValue
Вернет отложенную версию переданного значения, которая будет «отставать» от исходной на время, равное таймауту:
import < useDeferredValue >from 'react'; // . const [text, setText] = useState("text"); const deferredText = useDeferredValue(text, < timeoutMs: 2000 >);
Когда полезен новый хук: нужно реализовать отзывчивый и быстрый для пользователя интерфейс. Компонент, с которым взаимодействует пользователь, будет быстро перерисовываться на каждый ввод. При этом не будут происходить лишние перерендеры тяжелого компонента.
Улучшения Suspense
Suspense предназначен для отображения запасного интерфейса (спиннера) во время ожидания дочерних компонентов. Дочерние компоненты в это время могут выполнять асинхронные вызовы API, либо загружаться через lazy load.
Основное нововведение заключается в том, что фича стала стабильной. Получила большие архитектурные изменения под капотом и приобрела название «Конкурентные задержки» (Concurrent Suspense). Смена названия никак не отразится на пользователях React. Существенное изменение для пользователей заключается в рендере дочерних элементов внутри Suspense:
const App = () => < return ( >> >> ); >;
В React 17 компонент будет смонтирован и вызваны его эффекты. Затем он будет скрыт.
Теперь в React 18 компонент смонтируется только после того, как загрузится.
SuspenseList
Предназначен для определения порядка, в котором загружаются и отображаются пользователю напрямую вложенные компоненты Suspense и SuspenseList.
Бывают случаи, когда на UI необходимо отобразить компоненты в определенном порядке. Если обернуть их в SuspenseList, то React не отобразит компонент, пока не загрузится предыдущий из списка.
Потоковый SSR
Внесены большие улучшения в Suspense Server-Side-Rendering (SSR). Рассмотрим основные фичи:
Выборочная гидратация.
Метод hydrate() используется в SSR и позволяет повесить обработчики событий на узлы DOM-дерева, которые были отрендерены на стороне сервера. Это позволяет улучшить опыт клиента при первой загрузки страницы.
React начнет гидратацию компонентов с учетом взаимодействия пользователя с содержимым сайта. Например, при клике на комментарий React приоритезирует гидратацию HTML родительских блоков.
Еще одна особенность в том, что React не будет блокировать UI во время гидратации — этот процесс будет происходить во время простоя браузера. Поэтому пользовательские события будут обрабатываться сразу.
Потоковая отправка HTML
Позволяет отправить HTML клиенту без загрузки всех данных для рендера на сервер. Как только данные будут получены, они отрендерятся на сервере и отправятся на клиент. Например, есть блок с комментариями, и мы можем асинхронно загружать по ним информацию, отдавая HTML. Когда комментарии будут получены, отрендерить их и отправить клиенту в конце HTML-документа.
Что нужно сделать, чтобы пользоваться новыми функционалом React 18?
Обновление. Установка последней версии
npm install react react-dom
React 18. Что нового?
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Новые фичи
React
- useId — это новый хук для создания уникальных идентификаторов как на клиенте, так и на сервере, избегая при этом hydration несоответствий. Это в первую очередь полезно для библиотек компонентов, интегрирующихся с API, для которых требуются уникальные идентификаторы. Это решает проблему, которая уже существует в React 17 и более ранних версиях, но еще более важна в React 18 из-за того, что новый рендерер сервера доставляет HTML не по порядку.
- startTransition и useTransition позволяют помечать некоторые обновления состояния как несрочные. Другие обновления состояния по умолчанию считаются срочными. React позволит срочным обновлениям состояния (например, обновлению ввода текста) прерывать несрочные обновления состояния (например, отображение списка результатов поиска).
- useDeferredValue позволяет отложить повторный рендеринг несрочной части дерева. Он похож на debouncing, но имеет несколько преимуществ по сравнению с ним. Фиксированной задержки по времени нет, поэтому React попытается выполнить отложенный рендеринг сразу после того, как первый рендер отобразится на экране. Отложенный рендеринг может быть прерван и не будет блокировать ввод данных пользователем.
- useSyncExternalStore — это новый хук, который позволяет внешним хранилищам поддерживать параллельное чтение, заставляя обновления в хранилище быть синхронными. Он устраняет необходимость в useEffect при реализации подписок на внешние источники данных и рекомендуется для любой библиотеки, которая интегрируется со сторонним состоянием по отношению к React.
- useInsertionEffect — это новый хук, который позволяет библиотекам CSS-in-JS решать проблемы с производительностью при внедрении стилей во время рендеринга. Если вы не планируете создавать библиотеку CSS-in-JS, мы не ожидаем, что вы когда-либо будете это использовать. Этот хук запустится после изменения DOM, но до того, как эффекты лейаута узнают об этом. Это решает проблему, которая уже существует в React 17 и более ранних версиях, но еще более важна в React 18, поскольку React уступает браузеру во время одновременного рендеринга, давая ему возможность пересчитать лейаут.
React DOM Client
Новое API теперь экспортируются из react-dom/client:
- createRoot: новый метод создания корня для рендеринга или анмаунта. Используйте его вместо ReactDOM.render. Без него новые функции в React 18 не работают.
- hydrateRoot: новый метод гидратации приложения, отображаемого на сервере. Используйте его вместо ReactDOM.hydra в сочетании с новыми API-интерфейсами React DOM Server. Без него новые функции в React 18 не работают.
И createRoot, и hydrateRoot принимают новый параметр onRecoverableError, на случай, если вы хотите получать уведомления, когда React восстанавливается после ошибок во время рендеринга или гидратации для ведения журнала. По умолчанию React будет использовать reportError или console.error в старых браузерах.
React DOM Server
Новый API теперь экспортируются из react-dom/server и имеет полную поддержку потоковой передачи Suspense на сервере:
- renderToPipeableStream: для потоковой передачи в среде Node.
- renderToReadableStream: для современных сред выполнения, таких как Deno и Cloudflare.
Существующий метод renderToString продолжает работать, но не рекомендуется его использовать.
Deprecations
- react-dom: ReactDOM.render устарел. Его использование предупредит и запустит ваше приложение в режиме React 17.
- react-dom: ReactDOM.hydrate устарел. Его использование предупредит и запустит ваше приложение в режиме React 17.
- react-dom: ReactDOM.unmountComponentAtNode устарел.
- react-dom: ReactDOM.renderSubtreeIntoContainer устарел.
- react-dom/server: ReactDOMServer.renderToNodeStream устарел.
Критические изменения
React
- Автоматическая пакетная обработка: в этом релизе представлено улучшение производительности, которое меняет способ пакетной обработки обновлений React для автоматического выполнения большей пакетной обработки. Дополнительную информацию см. в разделе Автоматическая пакетная обработка для меньшего количества рендеров в React 18. В редких случаях, когда вам нужно отказаться, оберните обновление состояния в flushSync.
- Более строгий строгий режим: в будущем React предоставит функцию, позволяющую компонентам сохранять состояние между анмаунтами. Чтобы подготовиться к этому, React 18 вводит новую проверку только для разработки в строгом режиме. React автоматически анмаунтит и маунтит каждый компонент всякий раз, когда компонент создаётся в первый раз, восстанавливая предыдущее состояние при втором маунте. Если это сломает ваше приложение, рассмотрите возможность удаления строгого режима, пока вы не сможете исправить компоненты, чтобы они были устойчивы к повторному маунту с существующим состоянием.
- Согласованное время useEffect: React теперь всегда синхронно сбрасывает функции эффектов, если обновление было запущено во время дискретного события пользовательского ввода, такого как щелчок или событие нажатия клавиши. Раньше поведение не всегда было предсказуемым или последовательным.
- Более строгие ошибки гидратации: несоответствия гидратации из-за отсутствующего или дополнительного текстового содержимого теперь обрабатываются как ошибки, а не как предупреждения. React больше не будет пытаться «исправлять» отдельные узлы, вставляя или удаляя узел на клиенте в попытке сопоставить разметку сервера, и вернется к рендерингу клиента до ближайшей границы в дереве. Это гарантирует согласованность гидратированного дерева и позволяет избежать потенциальных дыр в конфиденциальности и безопасности, которые могут быть вызваны несоответствием гидратации.
- Эффекты лейаута с задержкой: когда дерево повторно приостанавливается и возвращается к резервному варианту, React теперь очищает эффекты лейаута, а затем воссоздает их, когда содержимое внутри границы снова отображается. Это устраняет проблему, из-за которой библиотеки компонентов не могли правильно измерить лейаут при использовании с Suspense.
- Новые требования к среде JS: React теперь зависит от современных функций браузеров, включая Promise, Symbol и Object.assign. Если вы поддерживаете более старые браузеры и устройства, такие как Internet Explorer, которые изначально не предоставляют современные функции браузера или имеют несовместимые реализации, рассмотрите возможность включения глобального полифилла в приложение.
Заметные изменения
React
- Компоненты теперь могут отображать undefined: React больше не выбрасывает ошибку, если вы возвращаете undefined из компонента. Это делает допустимые возвращаемые значения компонентов согласованными со значениями, разрешенными в середине дерева компонентов. Мы предлагаем использовать линтер, чтобы предотвратить такие ошибки, как забывание оператора return перед JSX.
- В тестах предупреждения об act теперь являются необязательными: если вы выполняете сквозные тесты, предупреждения об act не нужны. Мы ввели механизм отказа, поэтому вы можете включить их только для модульных тестов, где они полезны и выгодны.
- Нет предупреждений о setState для несозданных компонентов: раньше React предупреждал об утечках памяти, когда вы вызывали setState для несозданного компонента. Это предупреждение было добавлено для подписок, но люди в основном сталкиваются с ним в сценариях, где состояние настроек в порядке, а обходные пути ухудшают код. Мы удалили это предупреждение.
- Убрали скрытие журналов консоли: при использовании строгого режима React дважды визуализирует каждый компонент, чтобы помочь вам найти неожиданные побочные эффекты. В React 17 мы скрыли журналы консоли для одного из двух рендеров, чтобы облегчить чтение журналов. В ответ на отзывы сообщества о том, что это сбивает с толку, мы удалили скрытие. Вместо этого, если у вас установлен React DevTools, рендеры второго журнала будут отображаться серым цветом, и будет возможность (по умолчанию отключена) полностью их скрыть.
- Улучшенное использование памяти: React теперь очищает больше внутренних полей при анмаунте, что делает влияние незафиксированных утечек памяти, которые могут существовать в коде вашего приложения, менее серьезным.
React DOM Server
- renderToString: больше не будет возникать ошибка при приостановке на сервере. Вместо этого он выдаст резервный HTML-код для ближайшей границы , а затем повторит попытку рендеринга того же содержимого на клиенте. По-прежнему рекомендуется вместо этого переключиться на потоковый API, такой как renderToPipeableStream или renderToReadableStream.
- renderToStaticMarkup: больше не будет возникать ошибка при приостановке на сервере. Вместо этого он выдаст резервный HTML-код для ближайшей границы и повторит попытку рендеринга на клиенте.
Релиз React 18: что нового и интересного

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