[Первая партия крабов] Попробуйте React 18!

JavaScript React.js
[Первая партия крабов] Попробуйте React 18!

Команда 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

Ссылаться на

наконец

Если в статье есть ошибки, исправьте их в комментариях, если статья вам поможет, ставьте лайк и подписывайтесь.

Эта статья была впервые опубликована в моем личном публичном аккаунте: [код Secret Garden]:Попробуйте Реагировать 18!, добро пожаловать, чтобы следовать.

Интерфейсу Douyin срочно нужны таланты. Если вы хотите присоединиться к нам, добавьте меня в WeChat и свяжитесь со мной. Кроме того, если вы хотите присоединиться к фронт-энду, интервью, финансовому менеджменту и другим группам общения, или у вас есть какие-либо другие вещи, вы также можете добавить мой личный WeChatConardLiОбщайтесь вместе.