Что нового в React v18.0?
В React v18.0 появилось несколько интересных новых улучшений.
Когда год назад был анонсирован React 18, команда пообещала стратегию постепенного внедрения. Теперь, год спустя, это именно то, что они сделали, и вы можете обновить свое приложение до последней версии.
Для обновления с React 17 до 18 достаточно простого шага:
1) Установите последнюю версию:
npm install react@18 react-dom@18
Давайте углубимся в новые функции и обновления React 18.0.
1. Устаревший корневой API и новый корневой API
React 18 поставляет два корневых API, которые мы называем Legacy Root API и New Root API.
- Устаревший корневой API. Это существующий API, вызываемый с помощью
ReactDOM.render
. Это создает корень, работающий в «устаревшем» режиме, который работает точно так же, как React 17. Перед выпуском команда React добавит в этот API предупреждение о том, что он устарел, и переключится на New Root API. - Новый корневой API. Новый корневой API вызывается с помощью
ReactDOM.createRoot
. Это создает корень, работающий в React 18, который добавляет все улучшения React 18 и позволяет вам использовать параллельные функции. Это будет корневой API в будущем.
Использование:
//React 17
import * as ReactDOM from "react-dom"
import App from "App"
// The <App/> component is directly attached to a DOM element with the id of 'app':
ReactDOM.render(<App />, document.getElementById("app"))
New Root API использует ReactDOM.createRoot()
, создает новый корневой элемент, и в нем рендерится приложение React:
//React 18import * as ReactDOM from "react-dom" import App from "App"
// Create a root by using ReactDOM.createRoot(): const root = ReactDOM.createRoot(document.getElementById("app"))
// Render the main <App/> element to the root: root.render(<App/>)
Hydrating в Legacy Root API и Hydrating в новом Root API
import ReactDOM from 'react-dom' import App from 'App'
//React 17
const container = document.getElementById('app'); ReactDOM.hydrate(<App />, container)
//React 18const container = document.getElementById('root'); const root = ReactDOM.createRoot(container, { hydrate: true }); root.render(<App />);
2. Параллельные функции
В React 18 с параллельным рендерингом React может прерывать, приостанавливать, возобновлять или прекращать рендеринг. Это позволяет React быстро реагировать на взаимодействие с пользователем, даже если он находится в середине тяжелой задачи рендеринга.
До React 18 рендеринг представлял собой одну непрерывную синхронную транзакцию, и после начала рендеринга его нельзя было прервать.
Параллелизм — это фундаментальное обновление механизма рендеринга React. Параллелизм позволяет React прерывать рендеринг.
React 18 представляет собой основу параллельного рендеринга, а новые функции, такие как приостановка, рендеринг потокового сервера и переходы, основаны на параллельном рендеринге.
React 18 станет первым выпуском React, в котором будет добавлена поддержка параллельных функций, таких как:
startTransition
: позволяет поддерживать отзывчивость пользовательского интерфейса во время дорогостоящего перехода состояния.
В новом обновлении каждое обновление состояния относится к одной из следующих двух категорий: это либо срочное обновление, либо переходное обновление (для краткости — переход). Срочные обновления — это действия, на которые пользователь интуитивно рассчитывает мгновенно, например, на щелчок мыши или нажатие клавиши. Обновления перехода — это действия, которые допустимы с небольшой задержкой и во многих случаях ожидаются, например, поисковый запрос. startTransition
API помечает вызовы setState внутри него как переходы , что означает, что они прерываемы. Обновления перехода также запускаются синхронно, но пользовательский интерфейс не блокируется во время их выполнения.
import { startTransition } from "react"
// Urgent update that shows whatever is typed by the user: setInputValue(inputData);
// Transition updates are marked with startTransition: startTransition(() => { // A non-urgent, interruptable update of the search query: setSearchQuery(inputData); })
Если бы setSearchQuery(input)
не было помечено как обновление перехода, пользовательский интерфейс блокировался бы после каждого изменения ввода. Теперь, когда он помечен как несрочный, пользователь может искать что-либо, менять мнение и решать перейти на другую страницу до того, как пользовательский интерфейс будет обновлен в соответствии с изменением ввода, и ему не нужно ждать обновления пользовательского интерфейса, которое не представляет интереса.
Вы даже можете отслеживать состояние ожидания обновления перехода и показывать пользователю загрузочный пользовательский интерфейс, если хотите, используя useTransition
hook:
import { useTransition } from "react" const [isPending, startTransition] = useTransition()
// For example, you can show a loading spinner when it's pending: { isPending ? <LoadingSpinner /> : null }
useDeferredValue
hook помогает вам отложить обновление некоторой части пользовательского интерфейса на указанный период времени, сохраняя при этом отзывчивость страницы. Вы также можете дать ему необязательный тайм-аут. React попытается обновить отложенное значение, как только сможет. Если он не сделает этого в течение заданного периода времени ожидания, он принудительно запустит обновление, блокируя пользовательский интерфейс в процессе. Другими словами, отложенное значение обновляется с помощью обновления перехода, а не срочного обновления, благодаря чему ваш пользовательский интерфейс остается отзывчивым в процессе.
import { useDeferredValue } from "react"
const deferredValue = useDeferredValue(value, { timeoutMs: 3000, })
- useId: мы можем использовать этот новый хук для создания нового идентификатора на сервере и в клиенте.
function Checkbox() {
const id = useId();
return (
<>
<label htmlFor={id}>Do you follow This Dot on Twitter?</label>
<input id={id} type="checkbox" name="react"/>
</>
);
};
3. Автоматическое дозирование
React повторно отображает пользовательский интерфейс только один раз. Это означает, что React пакетирует (или группирует) все изменения вместе, поэтому вместо выполнения одного обновления состояния и повторного рендеринга пользовательского интерфейса, выполнения следующего обновления состояния и повторного рендеринга пользовательского интерфейса выполняется и то, и другое. состояния обновляет и повторно отображает пользовательский интерфейс только один раз.
Пакетная обработка — отличный механизм, который защищает нас от ненужного повторного рендеринга пользовательского интерфейса, но React 17 сделал это только в обработчиках событий. Использование цепочек обещаний, асинхронного кода или обработчиков событий нарушало это поведение. В React 18 пакетная обработка выполняется автоматически в собственных обработчиках событий, промисах и асинхронном коде.
function handleClickEvent() { // React 17: Re-rendering happens after both of the states are updated // This is also done in React 18 by default. setIsLoggedIn(loggedIn => !loggedIn); setCount(count => count+ 1); }
// For the following code blocks, React 18 does automatic batching, but React 17 doesn't. // 1. Promises: function handleClickEvent() { fetchData().then(() => { setIsLoggedIn(loggedIn => !loggedIn) setCount(count => count+ 1) }) }
// 2. Asynchronous code: setInterval(() => { setIsLoggedIn(loggedIn => !loggedIn) setCount(count => count+ 1) }, 3000)
// 3. Native event handlers: element.addEventListener("click", () => { setIsLoggedIn(loggedIn => !loggedIn) setCount(count => count+ 1) })
4. Новый Suspense SSR и селективная гидратация
- Рендеринг на стороне сервера, также известный как SSR, — это способ рендеринга веб-страниц, который позволяет создавать HTML-код из компонентов React непосредственно на сервере и делиться HTML-кодом с пользователями. Пользователи могут просмотреть предварительный просмотр страницы через SSR еще до того, как пакет JavaScript загрузится и запустится. Но иногда для обработки JavaScript на серверной части требуется много времени, и это время известно как время гидратации (процесс рендеринга компонентов React и добавления обработчиков событий в HTML-документ, отображаемый на стороне сервера, называется увлажнение).
- React 18 будет включать архитектурные улучшения производительности React SSR. Новое обновление позволит выполнять потоковую передачу HTML непосредственно на сервере, т. е. сервер отправляет части компонентов по мере их рендеринга с помощью другого компонента, известного как Suspense, который решает, какие части приложения могут загружаться дольше, а какие должны отображаться напрямую. Используя метод выборочной гидратации, компоненты, обернутые Suspense, больше не будут блокировать гидратацию. Каждый готовый компонент начнет заполняться, как только браузер получит его содержимое и код JavaScript.
‹Список приостановок› ‹/Список приостановок›
‹SuspenseList› позволяет вам координировать порядок появления содержимого узлов Suspense поддерева, которое он обертывает, даже если данные поступают в другом порядке. Обычно, если у вас есть несколько родственных границ саспенса, они разрешаются всякий раз, когда это возможно. Однако вы можете захотеть загружать компоненты в определенном порядке, независимо от того, в каком порядке они разрешаются.
import { Suspense, SuspenseList } from "react";
<SuspenseList revealOrder="forwards"> <Suspense fallback="Loading first item..."> <FirstItem /> </Suspense> <Suspense fallback="Loading second item..."> <SecondItem /> </Suspense> <Suspense fallback="Loading third item..."> <ThirdItem /> </Suspense> </SuspenseList>
В приведенном выше примере, даже если третий элемент загружается первым, он будет отображать Loading third item...
, пока не будет загружен первый элемент. Когда загружается первый элемент, отображается первый элемент вместе с запасным вариантом для второго и третьего. Только когда второй элемент загружен, все три могут быть отображены.
revealOrder
prop может принимать значения forwards
, backwards
и together
. forwards
и backwards
props позволяют внутренним границам приостановки разрешаться в прямом и обратном порядке. together
, с другой стороны, ждет разрешения всех границ, прежде чем визуализировать их все.
Вы также можете указать SuspenseList tail
prop. tail
prop может принимать значения collapsed
и hidden
. По умолчанию SuspenseList отображает все запасные варианты. Однако, если вы не хотите отображать резервные копии, вы можете использовать tail="hidden"
prop, а если вы хотите отображать не более одного резервного варианта, вы можете использовать tail="collapsed"
. Таким образом, вы можете создать множество запасных вариантов, не беспокоясь о загромождении области загрузки.
5. Строгий режим
Строгий режим в React 18 имитирует монтирование, размонтирование и повторное монтирование компонента с предыдущим состоянием. Это закладывает основу для многократного использования состояния в будущем, когда React может немедленно монтировать предыдущий экран, повторно монтируя деревья, используя то же состояние компонента перед размонтированием.
Строгий режим гарантирует устойчивость компонентов к многократному монтированию и размонтированию эффектов.
6. Теперь компоненты могут отображать undefined
React больше не выдает ошибку, если вы возвращаете undefined
из компонента. Разрешенный компонент возвращает значения, соответствующие допустимым значениям в середине дерева компонентов. Команда React предлагает использовать линтер, чтобы предотвратить такие ошибки, как забывание оператора return перед JSX.
7. Нет предупреждения setState
о несмонтированных компонентах
Ранее React предупреждал об утечке памяти, когда вы вызывали setState
для несмонтированного компонента. Это предупреждение было добавлено для подписок, но люди в основном сталкивались с ним в сценариях, где состояние настройки было в порядке, а обходные пути ухудшали код.
Заключение
Как мы видим, React 18 представил готовые улучшения и новые функции, которые выглядят невероятно. Это открыло путь для новых возможностей в разработке приложений React.js.
Ресурсы: