Наконец-то ожидание закончилось!
React, одна из наиболее широко используемых библиотек JavaScript, наконец-то выпустила релиз-кандидат своей долгожданной версии 18 или React 18. Это означает, что в финальной/стабильной версии вообще ожидается лишь несколько изменений.
Знание React требуется для понимания обновлений React 18. Если вы новичок, просто следуйте этой статье для дорожной карты в React.
Посмотрим, что это принесет!
Новый корневой API
React 18 имеет два корневых API: старый корневой API и новый.
Что такое корневой API?
Согласно официальным документам React, «корень» — это указатель на структуру данных верхнего уровня React для отслеживания дерева для рендеринга.
Устаревший корневой API
Существующий корневой API называется ReactDOM.render. В настоящее время корень прикреплен к элементу DOM, и доступ к нему можно получить через узел DOM.
Он будет работать точно так же, как в React 17. Однако консоль выдаст предупреждение, указывающее на его устаревание и переход на последнюю версию API.
import React from 'react'; import ReactDOM from 'react-dom'; import './index.scss'; import App from './App ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );
Новый корневой API
Он поставляется с ReactDOM.createRoot, включает новый параллельный рендеринги открывает доступ ко всем улучшениям, представленным в Реагировать 18.
import * as ReactDOMClient from 'react-dom/client'; import App from 'App'; const container = document.getElementById('app'); // Create a root. const root = ReactDOMClient.createRoot(container); // Initial render: Render an element to the root. root.render(<App tab="home" />); // During an update, there's no need to pass the container again. root.render(<App tab="profile" />);
Функция createRoot сначала создаст корень, а затем вызовет метод render для него.
Как справиться с гидратацией с помощью нового Root API?
Гидратация теперь обрабатывается через hydraRoot API.
import * as ReactDOMClient from 'react-dom/client'; import App from 'App'; const container = document.getElementById('app'); //Before // Render with hydration. ReactDOM.hydrate(<App tab="home" />, container); //After // Create *and* render a root with hydration. const root = ReactDOMClient.hydrateRoot(container, <App button="add" />); // You can later update it. root.render(<App button="update" />);
Обратный вызов рендеринга и новый корневой API
Обратный вызов рендеринга удален, поскольку он не поддерживает улучшения, предоставляемые частичной гидратацией и потоковой передачей SSR.
import * as ReactDOMClient from 'react-dom/client'; const rootElement = document.getElementById("root"); // Don't do this ReactDOMClient.render(<App />, rootElement, () => console.log("renderered")); // Do this const root = ReactDOMClient.createRoot(rootElement); root.render(<App callback={() => console.log("renderered")} />);
Вместо этого React рекомендует использовать requestIdleCallback, setTimeout или обратный вызов ref в корне.
Краткий обзор различий между устаревшим и новым корневым API
- Обратный вызов рендеринга был удален, а работа функции гидратации изменена.
- Корень — это объект, и любая функция для обновления корня применяется к этому объекту, а не к DOM.
Автоматическое дозирование
Вы когда-нибудь обновляли несколько состояний в одной функции, вызываемой обработчиком событий? Вы могли заметить, что все состояния обновляются в одном рендере. Это называется автоматическим пакетированием.
Пакетная обработка — это когда React группирует несколько обновлений состояния в один повторный рендеринг для повышения производительности.
До React 18 пакетная обработка по умолчанию выполнялась только в обработчиках событий React.
Двигаясь вперед с новым корневым API, пакетная обработка может выполняться независимо от источника, например промисов, setTimeout, собственных обработчиков событий. Обновление улучшит общую производительность и время рендеринга.
Отключить автоматическую пакетную обработку
Если вариант использования требует обновления состояния и ожидания ответа перед выполнением другого действия, ReactDOM. flushSync()приходит на помощь.
import { flushSync } from 'react-dom';
function handleClick() {
flushSync(() => {
// setState function
});
// React has updated the DOM by now
flushSync(() => {
// setState function
});
// React has updated the DOM by now
}
Рендеринг на стороне сервера Suspense/Streaming (SSR) и выборочная гидратация
На языке непрофессионала под рендерингом на стороне сервера понимается создание HTML-контента на сервере и его предоставление клиенту до тех пор, пока JavaScript не будет полностью загружен и обслужен.
Недостатки в текущей архитектуре React SSR
- Весь JS должен быть загружен до гидратации, и тогда компоненты станут интерактивными.
- Данные, такие как вызовы API, должны быть уже готовы на стороне сервера, так как они не будут ждать.
- Все компоненты должны быть гидратированы перед взаимодействием с ними.
Архитектура React 18 SSR
В отличие от текущей SSR, которая придерживается подхода «все или ничего», React 18 вносит революционные изменения в этом отношении, позволяя использовать потоковую передачу HTML, выборочную гидратацию и отложенную загрузку компонентов в SSR.
1. Потоковая передача HTML
Обертывание любого компонента с помощью ‹suspense›‹/suspense›укажет React не ждать этого компонента. Вместо этого он начнет потоковую передачу HTML, и когда данные для этого кода, завернутые в Suspense, будут готовы на сервере, дополнительный HTML будет отправлен в тот же поток с минимальным количеством встроенных JS для размещения в нужном месте.
Для потоковой передачи HTML на сервер вместо renderToString следует использовать API renderToPipeableStream.
Это поможет преодолеть проблему наличия полных данных перед рендерингом чего-либо.
2. Выборочная гидратация и ленивая загрузка на SSR
Функция Lazy в React обеспечивает ленивую загрузку на стороне клиента, то есть будет загружен только JS требуемого компонента, а не все приложение.
Прежде чем использовать выборочную гидратацию, вы должны подписаться на новый API createRoot.
Обертывание продуктов говорит React разблокировать остальные компоненты от потоковой передачи, и нет необходимости ждать загрузки всего JS перед гидратацией.
Пока компоненты увлажняются, React будет отдавать приоритет самой важной части экрана в зависимости от взаимодействия с пользователем.
import { lazy } from 'react'; const Products = lazy(() => import('./products.js')); <Suspense fallback={<Spinner />}> <Products /> </Suspense>
Новые API
1. Параллельный рендеринг
- API startTransition
Работа с огромными объемами данных и обновление больших состояний часто замедляют или зависают пользовательский интерфейс.
На помощь приходит API startTransition, который переводит обновления состояния в несрочные и выполняет сложные задачи в фоновом режиме. Пользовательский опыт остается бесшовным.
import { useTransition, startTransition } from 'react'; // Urgent: Show what was typed setInputValue(input); // Mark any state updates inside as transitions startTransition(() => { // Transition: Show the results setSearchQuery(input); });
Он также предоставляет перехватчик useTransitionдля проверки состояния переходов.
import { useTransition } from 'react'; const [isPending, startTransition] = useTransition(); {isPending && <Spinner />}
- useDeferredValue
import { useDeferredValue } from "react";
const deferredValue = useDeferredValue(text, { timeoutMs: 2000 });
Хук возвращает отложенную версию переданного значения. Он обычно используется, чтобы поддерживать отзывчивость интерфейса, когда у вас есть что-то, что отображается немедленно на основе пользовательского ввода, и что-то, что должно ждать выборки данных.
2. идентификатор использования
useId — это API для создания уникальных идентификаторов как на клиенте, так и на сервере, избегая при этом несоответствий гидратации.
const id = useId(); <input type="checkbox" name="react" id={id} />
Улучшения в Suspense с помощью SuspenseList
SuspenseList вступает в действие, когда нескольким компонентам требуется выборка данных и непредсказуемые заказы.
SuspenseList работает только с ближайшими к нему компонентами Suspense и SuspenseList. Он не ищет границы глубже одного уровня. Однако можно вкладывать несколько компонентов SuspenseList друг в друга для создания сеток.
<SuspenseList revealOrder="forwards">
<Suspense fallback={'Loading...'}>
<ProfilePicture id={1} />
</Suspense>
<Suspense fallback={'Loading...'}>
<ProfilePicture id={2} />
</Suspense>
<Suspense fallback={'Loading...'}>
<ProfilePicture id={3} />
</Suspense>
...
</SuspenseList>
В SuspenseList компонент не будет отображаться до тех пор, пока предыдущий не получит данные и не будет готов.
Он принимает два реквизита: revealOrder (вперед, назад, вместе) определяет порядок, в котором перечисленные компоненты должны отображаться, а хвост (свернутый, скрытый) определяет порядок выгрузки элементов в Показан SuspenseList.
Краткое содержание
Учитывая архитектурные изменения, которые приносит React 18, сообщество React взволновано. Это обеспечит лучший пользовательский интерфейс, UX, CX, а более надежные и эффективные веб-приложения уже не за горами.
Следите за обновлениями!
Подключаемся по LinkedIn.