😶

個人的 React “メモ”

2023/12/24に公開

GAOGAO アドベントカレンダー2023 12/20の記事です。

https://qiita.com/advent-calendar/2023/gaogao

React のレンダリング最適化においてメモ化を使わなくても十分最適化できる、と聞きつけたので、その他レンダリング最適化の手法について調べてみました。

サンプルコード

問題点:count が更新されるごとに <HeavyList> の再レンダリングが発生する

import { useState } from 'react';

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount((prevCount) => prevCount + 1)}>
        Increment
      </button>
      <HeavyList />
    </div>
  );
};

結論

Compsoition を用いる。

  export default function App() {
    return (
+     <Counter>
        <HeavyList>
+     </Counter>
    )
  };

+ function Counter({ children }) {
    const [count, setCount] = useState(0);

    return (
      <div>
        <p>Count: {count}</p>
        <button onClick={() => setCount((prevCount) => prevCount + 1)}>
          Increment
        </button>
+       {children}
      </div>
    );
  };

Comoposition とは

ReactNode 型の Props を扱うことで、これにより children としてコンポーネントを渡すことが可能となる。 ThemaProvider などでよく見かける形。

function App() {
  return (
+   <ComponentA>
      <ComponentB />
+   </ComponentA>
  )
}

function ComponentA({children}) {
  return (
    <div>
+     {children}
    </div>
  )
}

メリット

無駄な再レンダリングを回避できる

count が更新される度に <Counter> は再レンダリングされるが、children (<HeavyList>) は、前回 <App> から渡されたものと同じであるため <HeavyList> 自体は再レンダリングされない。

https://twitter.com/asidorenko_/status/1618901182508048388

Props Drilling を回避できる

https://twitter.com/asidorenko_/status/1623751929863016450

感想

調べてみると何年も前から提言されていることではあったし、公式ドキュメントにも記載されていた。

https://overreacted.io/before-you-memo/
https://ja.react.dev/learn/passing-props-to-a-component#passing-jsx-as-children

とはいえ RSC や React Forget に影響されて、近頃その重要性がさらに増していると思うので、このタイミングで理解を深めることができてよかった。

① RSC

RSC によって、「サーバーサイドで実行するコンポーネント」と「クライアントコンポーネントで実行するコンポーネント」を区別する。また、RSC では Client Component の中に ServerComponent を配置することができるが、これは Composition によって実現されている。

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#supported-pattern-passing-server-components-to-client-components-as-props

② React Forget

React では 2023 年現在 React Forget と呼ばれる最適なコンパイラーが開発されている。
React のプログラミング・モデルを維持しながら、再レンダリングのコストを最小化するために、useMemo とuseCallback 呼び出しに相当するものを自動的に生成するコンパイラーとのこと。

https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-optimizing-compiler

Discussion