React18の新機能

React チームは、2022 年 3 月 29 日に React の第 18 バージョンを正式にリリースしました。
この記事では、 React 18 の新機能、React Concurrent Mode (コンカレント モード) の実装、および簡単なアップグレード ガイドを簡単に紹介します。

新機能

自動バッチ処理

React は、React 18 よりずっと前から状態更新をバッチ処理できました。

function App() {
    
    
  const [count, setCount] = useState(0);

  const [flag, setFlag] = useState(false);

  function handleClick() {
    
    
    setCount((c) => c + 1); // Does not re-render yet

    setFlag((f) => !f); // Does not re-render yet

    // React will only re-render once at the end (that's batching!)
  }

  return (
    <div>
      <div>{
    
    count}</div>
      <button onClick={
    
    handleClick}>Next</button>
    </div>
  );
}

上の例では、ユーザーがボタンをクリックすると状態が 2 回更新されますが、状態が更新されるたびに再レンダリングが発生するのは当然です。ただし、これら 2 つの更新は一度に合成できるため、不必要な再レンダリングによるパフォーマンスの損失が軽減されます。

このバッチ処理は、React のネイティブ イベント内の更新に限定されます。

React 18 では、バッチ処理でサポートされる操作の範囲が拡張されました: Promise、setTimeout、ネイティブ イベント ハンドラーなど。これらの非 React ネイティブ イベントの内部更新もマージされます。

// Before: only React events were batched.

setTimeout(() => {
    
    
  setCount((c) => c + 1);

  setFlag((f) => !f);

  // React will render twice, once for each state update (no batching)
}, 1000);

// After: updates inside of timeouts, promises,

// native event handlers or any other event are batched.

setTimeout(() => {
    
    
  setCount((c) => c + 1);

  setFlag((f) => !f);

  // React will only re-render once at the end (that's batching!)
}, 1000);

トランジション

Transitions は React の 1 つで、高品質の更新と非高品質の更新を区別するために使用されます新概念

  • 高品質の更新/レンダリング: マウスのクリック、入力、およびリアルタイムでの高い対話性を必要とするその他の更新シナリオを含め、フリーズはユーザーの対話的な動作に影響を及ぼし、ユーザーは明らかにページ全体が動かなくなっているように感じます。

  • 非高品質の更新/レンダリング: ユーザー操作に関係のない通常の UI 更新、およびリアルタイム更新に対する高度な要件を持たない一部のシナリオ。

サスペンス

Suspense は、UI の読み込み状態を宣言するために React によって提供される API です。
<ComponentThatSuspends /> <Sibling /> </Suspense>
上記のコード文字列では、ComponentThatSuspends コンポーネントがデータ処理を要求すると、React はその場所に Loading コンポーネントを表示します。

サスペンスは React 16 および 17 でも利用できますが、完全ではなく、多くの機能がまだ準備ができていません。React チームの計画では、Suspense の完全な本体は Concurrent React に基づいているため、React 18 では Suspense が以前と比べていくつかの変更を加えています。

SSRのサスペンス

React 18 より前の SSR では、クライアントは、HTML データがサーバーに一度にロードされるのを待機し、ハイドレーションを開始する前にすべての JavaScript がロードされるのを待機し、すべてのコンポーネントが対話できるようになる前にすべてのコンポーネントがハイドレートされるのを待機する必要があります。つまり、データの取得(サーバー)→HTMLへのレンダリング(サーバー)→コードの読み込み(クライアント)→ハイドレーション(クライアント)までのプロセスを完了する必要があります。このような SSR は、完全なインタラクティブ性を高速化するわけではなく、ユーザーが静的なページ コンテンツを認識する速度を向上させるだけです。

React 18のサスペンス:

  • <script>サーバーは、Suspense でラップされたコンポーネントがロードされるのを待たずに HTML を送信できます。代わりに、Suspense でラップされたコンポーネントはフォールバックのコンテンツ (通常はプレースホルダー (スピナー) であり、 HTML の位置は最小のインラインでマークされます)タグが付いていますコンポーネントのデータがサーバー上で準備できるのを待った後、React は残りの HTML を同じストリームに送信します。

  • ハイドレーションのプロセスは段階的に行われ、ハイドレーションを開始する前にすべての js がロードされるのを待つ必要がないため、ページの遅延が回避されます。

  • React は、ページ上のインタラクティブ イベント (マウス クリックなど) を事前にリッスンし、インタラクションが発生する領域の水分補給を優先します。

同時レンダリング

React 18 の最も重要なアップデートは、同時レンダリングが完全に有効になったことです。これは実際には新しい機能ではなく、実際には React の内部動作に対する大きな変更です。React レイアウトは、究極の同時レンダリングを目的として長い間使用されてきました。

質問

ページ要素が多く、頻繁に再レンダリングが必要なシナリオでは、React 15 でフレーム ドロップが発生します。根本的な原因は、多数の同時コンピューティング タスクがブラウザーの UI レンダリングをブロックすることです。JS 操作、ページ レイアウト、描画はすべてブラウザのメイン スレッドで実行され、相互に排他的です。JS 操作がメイン スレッドを占有し続けると、ページの更新が間に合わなくなります。再レンダリングをトリガーするために状態を更新すると、React はアプリケーションのすべてのノードを走査し、差分を計算して、UI を更新します。更新が開始されると、途中で中断することはできず、ツリー全体が走査されるまでメインスレッドを解放することはできません。ページ上に多くの要素がある場合、プロセス全体に 16 ミリ秒以上かかる可能性があり、ブラウザがフリーズすることがあります。

React 15 の実装によって引き起こされるブラウザのフリーズの鍵は、再レンダリングが開始されるたびに停止できないことであることがわかります。そのため、React チームは解決策を考えました。それは、再レンダリングを に変更することです可中断

一連の考え

  • 再レンダリング中の JS 計算はより小さな粒度のタスクに分割され、実行されたタスクはいつでも一時停止、継続、破棄できます。

  • JS の計算時間が 16 ミリ秒に達すると一時停止され、描画フレームのドロップの問題を防ぐために、メインスレッドが UI に描画を与えます。

  • ブラウザがアイドル状態のときに、以前に実行されなかった小さなタスクを引き続き実行します。

アップグレードガイド

  • 新しい API createRoot を使用するようにルート ノードのマウント方法を変更すると、古い API は引き続き互換性があり、createRoot を使用した後でのみ React 18 の新機能が利用可能になります。

  • React 18 では、上記の自動バッチ処理が有効になります。これは重大な変更と考えられますが、React は自動バッチ処理を終了するために flashSync API も提供します。使用方法は次のとおりです。

import {
    
     flushSync } from "react-dom";

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
}
  • flashSync が使用されない場合、2 つの setState は 1 回だけ再レンダリングされ、使用後に 2 回トリガーされます。

  • TS 型定義の大きな変更: 子を使用する場合、その型をコンポーネント props の定義に記述する必要がありますが、これまでは無視できました。

interface MyButtonProps {
    
    
  color: string;

  children?: React.ReactNode;
}
  • React 18 は IE をサポートしなくなりました。

おすすめ

転載: blog.csdn.net/hyqhyqhyqq/article/details/129675202