React.Memoでグリップする
React.memo
は、Reactの純粋なコンポーネントの機能を提供しますが、クラスベースのコンポーネントではなく機能ベースのコンポーネント用です。
memoization
は、高価な関数呼び出しの結果をキャッシュし、引数が同じ場合にキャッシュされたバージョンを返すことを意味するコンピュータサイエンスの専門用語です。
Reactの用語で:
渡されるprops
が同じである場合、MyNewComponent
が再レンダリングされることは望ましくありません。
簡単なカウンターの例
React.memoがどのように機能するかを頭に入れておくために、Codesandboxで次の例を作成しました。
ボタンがクリックされた回数をカウントするシンプルなアプリです。 下のスクリーンショットから、ページの上部にバナーが表示されていることがわかります。
Banner
がさまざまなタイプのUIコンポーネントであると想像してください。この場合、info
タイプのバナーを使用して、Banner
を次のように作成します。
<Banner type="info" />
CounterComponent
は次のようになります。
class CounterComponent extends Component { state = { buttonPressedCount: 0 }; render() { const { buttonPressedCount } = this.state; return ( <div className="new-component"> <h4>Button Pressed Count: {buttonPressedCount}</h4> <button onClick={() => this.setState({ buttonPressedCount: buttonPressedCount + 1 }) } > Increase Count </button> <Banner type="info" /> </div> ); } }
また、Banner
コンポーネントは次のようになります。
const Banner = props => { const { type } = props; if (type === "info") { return <div className="info-banner">I am an info banner</div>; } };
CounterComponent
では、ボタンをクリックするたびにbuttonPressedCount
変数を増やして、期待どおりの再レンダリングを行います。 これに伴う問題は、渡されるprops
が変更されていなくても、Banner
コンポーネントも再レンダリングされることです。
これを回避するために、props
が変更されていない場合に再レンダリングを停止するという点で、PureComponent
のように機能するmemo
を使用します。 更新されたコードは次のようになります。
const Banner = memo(props => { const { type } = props; if (type === "info") { return <div className="info-banner">I am an info banner</div>; } });
これで、Banner
コンポーネントは、props
が変更された場合にのみ再レンダリングされます。
これがReactメモの基本的な考え方です。
は同じ
では、もう少し進んで、カスタムの平等について話しましょう。 デフォルトでは、memo
は、小道具と小道具のオブジェクトのshallow
比較のみを行います。 2番目の引数を渡して、カスタムの同等性チェックを示すことができます。
React.memo(Component, [areEqual(prevProps, nextProps)]);
これはshouldComponentUpdate
に似ていますが、逆です。 shouldComponentUpdate
でtrue
を返すと、別のレンダリングが発生しますが、areEqual
はその逆です。
オブジェクトであるprop
人を受け入れるPerson
コンポーネントがあると想像してください。name
が同じであるかどうかを確認できます。
const areEqual = (prevProps, nextProps) => { return (prevProps.name === nextProps.name) }; React.memo(Person, areEqual);
結論
これはReactへの本当に素晴らしい追加であり、不必要な再レンダリングを心配することなく機能コンポーネントを使用することができます。 いつものように、この投稿で何か良いことを学んだことを願っています!