🍉

【最低限押さえておきたい】Reactレンダリング超基礎

2022/10/11に公開

はじめに

Reactのコンポーネントが画面に表示されるまでに"レンダリング" というプロセスを通る必要があります。

本記事では、React Docs Betaを読みながらそのプロセスの理解を図ります。

ReactのUIの描画

Reactでは、UI(コンポーネント)が描画(画面に表示)されるまでに以下の3つの工程を経る必要がある。

  1. Triggering a render
  2. Rendering the component
  3. Committing to the DOM

それぞれの工程について

【STEP1】 Triger a render

レンダリングのきっかけ(トリガーとなるもの)を検知すること。
ReactのコンポーネントがレンダリングされるきっかはReact Docs Betaによると二パターンあるそう。

  1. It’s the component’s initial render.
  2. The component’s (or one of its ancestors’) state has been updated.

1つ目は、コンポーネントの初期レンダリングです。
そして2つ目がそのコンポーネントまたはその祖先のコンポーネントのstateが更新された場合です。(いわゆる再レンダリングというやつです。)

【STEP2】 Rendering the component

初期レンダリング終了後、Reactはコンポーネントを呼び出して、何を画面に描画するかを決定します。
レンダリングとは、この「コンポーネントを呼び出す」ことである。
Next.jsなどのフレームワークを使用してしまうと、ここが隠蔽されがちになるらしいですね。

この一連が"初期レンダリング"になります。

On initial render, React will call the root component.
For subsequent renders, React will call the function component whose state update triggered the render.

React Docs Betaによると、
最初の初期レンダリングでは、rootのコンポーネントが呼び出されます。
※詳しくは、ターゲットのDOMツリーでcreateRootを呼び出し、そのrenderメソッドを使ってコンポーネントを呼び出します。

下記のサンプルコードで言うと、Appコンポーネントが初回のレンダリングで呼び出されることになります。

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  <React.StrictMode>
    <App />
 </React.StrictMode>
)

初期レンダリング以降では、レンダリングの発生のトリガーとなった状態(state)の更新が行われたコンポーネントやその子孫コンポーネントの再レンダリングが行われる。
基本的にはネストされたコンポーネントがなくなり、Reactが何を描画するか完全に把握できるまで再起的にレンダリングが実行されます。
※メモ化することで不用意な再レンダリングを防ぐことができます。

【STEP3】 Committing to the DOM

Reactはレンダリング終了後に、DOMの更新を行います。
ここでようやくUI(見た目)が変わったり変わらなかったります。(レンダリングまででは何も変わりません)

初期レンダリングでは、Reactは作成した全てのDOMノードをappendChild()を使用して画面上に描画します。
再レンダリングでは、Reactは状態(state)の更新が行われたコンポーネントのみをレンダリングプロセスで検知してDOMの更新を行います。

Reactは基本的に状態(state)などの差分検知したら、該当するコンポーネントのみ再レンダリングし、DOMの更新をします。

そのため、以下のサンプルコードでは、inputタグに何らかの文字を入力しても再レンダリング + DOMの更新はinputタグにしかなされないのでh1タグ側の文字が一瞬見えなくなるなどの現象は発生しません。

export default function Clock({ time }) {
  return (
    <>
            /** inputタグがレンダリングされても、その瞬間にh1タグに差分がなければ何も起こらない。 */
      <h1>{time}</h1>

      /** inputタグに値を入力しても、inputタグだけがDOMの更新が行われる */
      <input />
    </>
  );
}

まとめ

Reactのレンダリングには以下の三つの工程が存在します。

  1. Trigger
  2. Render
  3. Commit

そしてReactはレンダリングの差分が発生した場合のみDOMの更新を行う。

Discussion