レンダーとコミット
コンポーネントが画面に表示される前に、React によってレンダリングされる必要があります。このプロセスの手順を理解すると、コードがどのように実行されるかを考えるのに役立ち、その動作を説明できるようになります。
学習内容
- React におけるレンダリングの意味
- React がコンポーネントをレンダリングするタイミングとその理由
- コンポーネントを画面に表示する際の手順
- レンダリングが常に DOM 更新を生成するとは限らない理由
コンポーネントは、食材から美味しい料理を組み立てる厨房の料理人だと考えてください。このシナリオでは、React はお客様からのリクエストを受け取り、注文を届けるウェイターです。UI をリクエストして提供するこのプロセスには、3 つの手順があります。
- レンダーをトリガーする (お客様の注文を厨房に届ける)
- コンポーネントをレンダリングする (厨房で注文を準備する)
- DOM にコミットする (テーブルに注文を置く)
トリガー レンダー コミット
イラスト提供 レイチェル・リー・ネイバース
ステップ 1: レンダリングをトリガーする
コンポーネントをレンダリングする理由は 2 つあります。
- コンポーネントの初期レンダリングである。
- コンポーネント (またはその祖先のいずれか) のステートが更新された。
初期レンダリング
アプリが起動すると、初期レンダリングをトリガーする必要があります。フレームワークやサンドボックスでは、このコードが隠されている場合がありますが、createRoot
をターゲット DOM ノードで呼び出し、次にコンポーネントを使用して render
メソッドを呼び出すことで行われます。
import Image from './Image.js'; import { createRoot } from 'react-dom/client'; const root = createRoot(document.getElementById('root')) root.render(<Image />);
root.render()
呼び出しをコメントアウトして、コンポーネントが消えるのを確認してください!
ステートが更新されたときの再レンダリング
コンポーネントが最初にレンダリングされたら、set
関数を使用してステートを更新することで、さらにレンダリングをトリガーできます。コンポーネントのステートを更新すると、自動的にレンダリングがキューに入れられます。(これは、レストランの客が最初の注文をした後、喉の渇きや空腹の状態に応じて、お茶やデザートなど、さまざまなものを注文する様子を想像してください)。
ステート更新... ...トリガー... ...レンダー!
イラスト提供 レイチェル・リー・ネイバース
ステップ 2: React がコンポーネントをレンダーする
レンダーをトリガーすると、React はコンポーネントを呼び出し、画面に何を表示するかを判断します。「レンダー」とは、React がコンポーネントを呼び出すことです。
- 最初のレンダーでは、React はルートコンポーネントを呼び出します。
- 後続のレンダーでは、React は、状態の更新がレンダーをトリガーした関数コンポーネントを呼び出します。
このプロセスは再帰的です。更新されたコンポーネントが他のコンポーネントを返す場合、React は次にそのコンポーネントをレンダーし、そのコンポーネントも何かを返す場合は、次にそのコンポーネントをレンダーします。このプロセスは、ネストされたコンポーネントがなくなり、React が画面に何を表示する必要があるかを正確に把握するまで続きます。
次の例では、React は Gallery()
および Image()
を複数回呼び出します。
export default function Gallery() { return ( <section> <h1>Inspiring Sculptures</h1> <Image /> <Image /> <Image /> </section> ); } function Image() { return ( <img src="https://i.imgur.com/ZF6s192.jpg" alt="'Floralis Genérica' by Eduardo Catalano: a gigantic metallic flower sculpture with reflective petals" /> ); }
- 最初のレンダー中、React は DOM ノードを作成 して、
<section>
、<h1>
、および 3 つの<img>
タグを作成します。 - 再レンダー中、React は、前のレンダーから変更されたプロパティ(もしあれば)を計算します。この情報は、次のステップであるコミットフェーズまで何もしません。
深掘り
更新されたコンポーネント内にネストされたすべてのコンポーネントをレンダーするデフォルトの動作は、更新されたコンポーネントがツリー内で非常に高い位置にある場合、パフォーマンスにとって最適ではありません。パフォーマンスの問題が発生した場合は、パフォーマンスセクションで説明されているように、いくつかのオプトイン方法で解決できます。時期尚早な最適化は避けてください!
ステップ 3: React が DOM に変更をコミットする
コンポーネントのレンダー(呼び出し)後、React は DOM を変更します。
- 最初のレンダーの場合、React は
appendChild()
DOM API を使用して、作成したすべての DOM ノードを画面に表示します。 - 再レンダーの場合、React は、DOM を最新のレンダー出力に一致させるために必要な最小限の操作を(レンダー中に計算された!)適用します。
React は、レンダー間に違いがある場合にのみ DOM ノードを変更します。たとえば、これは親から毎秒異なるプロパティを渡して再レンダーするコンポーネントです。<input>
にテキストを追加して value
を更新できますが、コンポーネントが再レンダーされるときにテキストが消えないことに注目してください。
export default function Clock({ time }) { return ( <> <h1>{time}</h1> <input /> </> ); }
これは、この最後のステップ中に、React が新しい time
で <h1>
の内容のみを更新するためです。JSX 内で <input>
が前回と同じ場所にあることを認識するため、React は <input>
やその value
に触れません。
エピローグ: ブラウザペイント
レンダーが完了し、React が DOM を更新した後、ブラウザは画面を再ペイントします。このプロセスは「ブラウザレンダー」として知られていますが、ドキュメント全体での混乱を避けるために、「ペイント」と呼びます。

イラスト提供 レイチェル・リー・ネイバース