関数コンポーネントの再描画とは
関数が実行されて、HTML文書構造をreturnすることで、対象のDOMが再描画されます。
関数コンポーネントが再描画(再実行)されるタイミング
以下のようなときに再描画(再実行)されます。
- stateが変化した時
- propsが変化した時
- 親コンポーネントが再描画された時
React.memoについて
React.memoを使うと関数コンポーネントをメモ化することができ、上記した3の場合について、無駄な再描画を減らすことができます。
サンプルコード
例えば以下のようなParent.tsx、Hoge.tsx、Foo.tsxを作成します。
Hoge.tsxとFoo.tsxはメモ化したうえで、子コンポーネントとして使用します。
ボタンをクリックして親コンポーネントで定義したstateを変化させ、これら3つのコンポーネントの再描画の挙動について確認していきます。
Parent.tsx
import React from 'react'; import { Hoge } from '@/components/common/elements/Hoge'; import { Foo } from '@/components/common/elements/Foo'; export function Parent() { const [hoge, setHoge] = React.useState(0); const [foo, setFoo] = React.useState(0); function incrementHoge() { setHoge(hoge + 1); } function incrementFoo() { setFoo(foo + 1); } console.log('Parentを再実行します。'); return ( <> <button onClick={incrementHoge}>hoge + 1</button> <button onClick={incrementFoo}>foo + 1</button> <Hoge hoge={hoge} /> <Foo foo={foo} /> </> ); }
Hoge.tsx
import React from 'react'; type Props = { hoge: number; }; export const Hoge = React.memo(function Tmp({ hoge }: Props) { console.log('Hogeを再実行します。'); return <div>{hoge}</div>; });
Foo.tsx
import React from 'react'; type Props = { foo: number; }; export const Foo = React.memo(function Tmp({ foo }: Props) { console.log('Fooを再実行します。'); return <div>{foo}</div>; });
コードの解説
コンポーネントをメモ化していない場合、 hoge + 1
ボタンをクリックすると、実行結果に変化がないFoo.tsxまで再実行されてしまいます。
これは上記した「関数コンポーネントが再描画(再実行)されるタイミング」の「3. 親コンポーネントが再描画された時」に該当するためです。
このサンプルコードのように子コンポーネントをメモ化することで、 hoge + 1
ボタンをクリックしたときに、実行結果に変化がないFoo.tsxは再実行されないことがわかります。
同様に foo + 1
ボタンをクリックした場合には、実行結果に変化がないHoge.tsxは再実行されないことがわかります。