Reactの再レンダーの範囲を限定する方法
Reactの再レンダーの範囲を限定して、不毛な再レンダーを防ぐ方法を取り上げる。 本来は、propsが変更されていなかったとしても、親が再レンダーされれば子も再レンダーされる。
親が再レンダーされたとしても、子に渡されているpropsに変更がない場合は、子が再レンダーされるのは不毛である。
memoは「propsの変更がない場合は再レンダーしなくてもよい」と伝えるためのもので、不毛な再レンダーが発生するのを防ぐことができる。
再レンダーが必要な範囲だけを再レンダーさせる実装で、結果的に不毛な再レンダーを防ぐことができる。
下準備: 状態とそのセッターを関心事ごとに分割して、分割したものを一つひとつのcontextに割り当てる。
状態とセッターを分割する方法
状態を一つのstateで保持・一つのsetStateで変更させるのではなく、複数のstate/setStateのペアに分割する。
などの方法がある。
Providerコンポーネントの実装
分割したcontextのproviderを被せるためのコンポーネントを用意する。
code:tsx
const Provider: FC<{ readonly children?: ReactNode }> = (props) => {
return (
<ExampleSetter1.Provider value={setState1}>
<ExampleData1.Provider value={state1}>
<ExampleSetter2.Provider value={setState2}>
<ExampleData2.Provider value={state2}>
{props.children}
</ExampleData2.Provider>
</ExampleSetter1.Provider>
</ExampleData1.Provider>
</ExampleSetter1.Provider>
);
}
状態を参照するコンポーネントの実装
状態を参照したい場合は、前に実装したcontextの内部のstateを参照する。
使いたい状態に対応するcontextをuseContextフックを通して参照する。
contextを参照するコンポーネントは、Providerコンポーネントのchildrenに渡すようにする。
Providerコンポーネントのprops.childrenはProviderコンポーネントの子コンポーネントではないので、Providerコンポーネントが参照しているstateが変更されても、全部が再レンダーされることはない。
Providerコンポーネントが参照しているstateが変更されても、props.childrenのうち、変更されたstateを参照しているコンポーネントだけが再レンダーされる。
単一責任ではない状態があったり、それが何か所にもあったりするのは見通しが悪くなる。memoを検討するよりも、contextを使って状態を分割する方法を積極的に活用したほうが、良いコンポーネント設計を実践できそう。mgn901.icon
参考にした資料