Команда React недавно выпустила альфа-версию React 18. Этот выпуск предназначен в основном для улучшения приложений React.并发渲染Вы можете попробовать следующие новые функции в React 18:
- новый
ReactDOM.createRoot()API (заменяетReactDOM.render()) - новый
startTransitionAPI (для неэкстренных обновлений) - Автоматическая пакетная оптимизация для рендеринга (в основном решает проблему невозможности пакетной обработки в асинхронных обратных вызовах)
- служба поддержки
React.lazyНовая архитектура SSR (поддерживает<Suspense>компоненты)
Нет, эта версия только что выпущена, и многие друзья в сообществе уже хотят попробовать ее, и мне не терпится попробовать ее с большими парнями в сообществе. Заинтересованные друзья могут подписаться на мою запись, чтобы попробовать:
Установите React 18 Альфа
Чтобы опробовать React 18 Alpha в своем проекте, попробуйте следующую команду:
npm install react@alpha react-dom@alpha
# or
yarn add react@alpha react-dom@alpha
если вы используетеCreate React AppПри инициализации проекта вы можете столкнуться сreact-scriptsвызванныйcould not resolve dependencyошибка:
Could not resolve dependency:
peer react@">= 16" from react-scripts@4.0.3
Вы можете попробовать добавить--forceДля решения этой проблемы:
npm install react@alpha react-dom@alpha --force
ReactDOM.createRoot()
В версии React 18ReactDOM.createRoot()заменяет обычную запись программыReactDOM.render()метод.
Этот метод в основном предназначен для предотвращения сбоя вашего приложения из-за несовместимых обновлений React 18.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
const container = document.getElementById('root');
// Create a root.
const root = ReactDOM.createRoot(container);
// Render the top component to the root.
root.render(<App />);
При обновлении до React 18, если вы также используете функцию redner в качестве записи программы, консоль распечатает журнал ошибок, чтобы напомнить вам об использовании createRoot() , и только после этого метода вы сможете использовать новые функции React 18.
Автоматическая пакетная обработка рендеринга
В React есть классический вопрос для интервью:setStateСинхронный он или асинхронный, я часто буду спрашивать во время интервью, в частности, я представил его в статье двухлетней давности:
Изучите механизм выполнения setState из практических задач.
class Example extends React.Component {
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val);
this.setState({val: this.state.val + 1});
console.log(this.state.val);
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val);
this.setState({val: this.state.val + 1};
console.log(this.state.val);
}, 0);
}
render() {
return null;
}
};
Например, в приведенном выше коде рассмотрим два случая:
- Предполагая, что React вообще не имеет механизма пакетной обработки, тогда выполнение setState немедленно вызовет рендеринг страницы, а порядок печати должен быть 1, 2, 3, 4.
- Предполагая, что React имеет идеальный механизм пакетной обработки, тогда весь рендеринг должен обрабатываться единообразно после выполнения всей функции, а порядок печати должен быть 0, 0, 0, 0.
Фактически, до React 18 приведенный выше код печатался в порядке 0, 0, 2, 3.
Основная причина этой проблемы в том, чтоReactФункция события отличается от механизма пакетирования состояний в асинхронном обратном вызове. Вне асинхронного обратного вызова все рендеринги могут быть объединены в один, внутри асинхронного обратного вызова они не будут объединены и будут рендериться несколько раз.
На самом деле, в большинстве сценариев нам нужно обновить состояние в callback-функции после вызова интерфейса или выполнения каких-то других действий, и описанный выше механизм пакетирования будет очень безвкусным.
Теперь версия React 18 решает эту проблему, независимо от того, обновляете ли вы состояние в Promise, setTimeout или другом асинхронном обратном вызове, пакет будет запущен, и приведенный выше код действительно всегда будет печатать0、0、0、0!
Разве это не здорово! Вопрос из интервью, который React помог нам устранить 😎.
Обычно с пакетной обработкой проблем нет, но она может не подходить для некоторых особых требований (например, для получения некоторого контента из DOM сразу после изменения состояния), мы можем использоватьReactDOM.flushSync()Выход из партии:
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
RickyВ этой статье (https://github.com/reactwg/react-18/discussions/21) подробностиAutomatic batching, если вы заинтересованы, вы можете перейти в область комментариев, чтобы обсудить вместе.
Поддержка ленивой загрузки в SSR
React.lazyФункции позволяют обрабатывать динамически импортированные компоненты так же, как визуализацию обычных компонентов.React.lazyПринимает функцию, которую необходимо вызвать динамическиimport(). он должен вернутьPromise,ДолженPromiseнужноresolveОдинdefault exportРеагировать на компоненты.
const MonacoEditor = React.lazy(() => import('react-monaco-editor'));
React.lazyдолжны сотрудничать<Suspense>можно лучше использовать вSuspenseРендеринг в компонентеlazyкомпонент, который можно использовать во время ожидания загрузкиlazyизящно деградировать компоненты (например, рендеринг некоторыхloadingЭффект ).fallbackСвойство принимает все, что вы хотите отобразить во время загрузки компонента.Reactэлемент.
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// Displays <Spinner> until OtherComponent loads
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
существуетReact 18Ранее режим SSR не поддерживался для использованияSuspenseкомпонент, а серверные компоненты в React 18 также поддерживают использование<Suspense>сейчас: если вы завернете компонент в<Suspense>, сервер сначалаfallbackКомпоненты в потоке передаются как HTML, и как только основной компонент загружается, React отправляет новыйHTMLдля замены компонента.
<Layout>
< Article />
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
</Layout>
Например, приведенный выше код,<Article>Компонент будет отображаться первым,<Comments>компоненты будутfallbackзаменить<Spinner>. однажды<Comments>После загрузки компонента React отправит его в браузер, заменив<Spinner>компоненты.
Dan AbramovВ этой статье (https://github.com/reactwg/react-18/discussions/37) подробно описывает этот механизм, и если вам интересно, вы можете обсудить его в области комментариев.
startTransition API
startTransition— это новый API, добавленный в React 18, который позволяет различать非紧急обновление статуса.
Вот, например, сейчас такая сцена: мы идемInputПоле вводит значение, а затем необходимо предоставить некоторые данные, отфильтрованные по введенному нами значению.
Поскольку вам необходимо динамически отображать отфильтрованное значение каждый раз, вы можете сохранить входное значение вstate, ваш код может выглядеть так:
setInputValue (input) ;
setSearchQuery (input) ;
Прежде всего, значение, введенное пользователем, должно отображаться немедленно, но отфильтрованные данные ассоциации могут не нуждаться в такой быстрой визуализации.Если мы не будем выполнять какую-либо дополнительную обработку, до React 18 все обновления будут отображаться немедленно.Если У вас много необработанных данных, поэтому каждый раз, когда вы вводите новое значение, объем вычислений, которые вам необходимо выполнить (фильтрация квалифицированных данных в соответствии с введенным значением), очень велик, поэтому после каждого пользователя может возникнуть задержка. Вход.
Поэтому в прошлом мы могли добавлять некоторые операции защиты от сотрясений, чтобы искусственно задерживать вычисление и рендеринг отфильтрованных данных.
Новый API startTransition позволяет нам помечать данные какtransitionsусловие.
import { startTransition } from 'react';
// Urgent: Show what was typed
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});
все вstartTransitionОбновления в обратном вызове считаются非紧急处理, если есть более срочное обновление (например, пользователь вводит новое значение), указанное выше обновление будет прервано, и обновление не будет продолжаться до тех пор, пока не будут выполнены другие срочные операции.
Как же не изящнее, чем мы добиваемся стабилизации искусственного 😇
В то же время React также предоставляет намisPendingзнак переходаHook:
import { useTransition } from 'react' ;
const [ isPending , startTransition ] = useTransition ( ) ;
вы можете использовать его и некоторыеloadingИспользуйте анимацию в сочетании с:
{ isPending && < Spinner / > }
RickyВ этой статье (https://github.com/reactwg/react-18/discussions/41) подробностиstartTransition, если вы заинтересованы, вы можете перейти в область комментариев, чтобы обсудить вместе.
План выпуска React 18
Официальное введение React 18 (https://github.com/reactwg/react-18/discussions/4), упомянутые в двух других APIuseDeferredValue,<SuspenseList>еще нетreleased, мы воспользуемся им в следующий раз, вот график выпуска React 18:
-
React 18 AlphaВерсия: доступна сейчас - Публичная бета-версия: как минимум через несколько месяцев после альфа-версии
- Релиз RC: как минимум через несколько недель после бета-релиза
- Общий релиз: как минимум через несколько недель после релиза RC
Ссылаться на
- GitHub.com/реагировать на WG/Hot…
- GitHub.com/реагировать на WG/Hot…
- GitHub.com/реагировать на WG/Hot…
- blog.bit SRC.IO/trying-vomit-…
наконец
Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь.
Эта статья была впервые опубликована в моем личном публичном аккаунте: [код Secret Garden]:Попробуйте Реагировать 18!, добро пожаловать, чтобы следовать.
Интерфейсу Douyin срочно нужны таланты. Если вы хотите присоединиться к нам, добавьте меня в WeChat и свяжитесь со мной. Кроме того, если вы хотите присоединиться к фронт-энду, интервью, финансовому менеджменту и другим группам общения, или у вас есть какие-либо другие вещи, вы также можете добавить мой личный WeChatConardLiОбщайтесь вместе.