React の memo API
次のフックについて説明する前に、
コンポーネントの props が変更されない場合の
再レンダリングを防ぐのに役立つ便利な API
memoについても触れておく必要があります。
例を使って見ていきましょう。
2つの入力フィールドを持つ
コンポーネント App を作成します。
ここでは名前と名字を入力するものとします:
return (
<div>
<label>
name:
<input value={name} onChange={(e) => setName(e.target.value)} />
</label>
<br />
<label>
surname:
<input value={surn} onChange={(e) => setSurn(e.target.value)} />
</label>
</div>
);
コンポーネントの先頭に、 それぞれの状態を追加しましょう:
const [name, setName] = useState('');
const [surn, setSurn] = useState('');
さらに、子コンポーネント
Child.js を作成しましょう。
入力された名前を表示する挨拶文を出力します。
また、このコンポーネントがレンダリングされるたびに、
コンソールに文字列 'child render' が
出力されるようにします:
function Child({ name }) {
console.log('child render');
return <h3>Hello {name}!</h3>;
}
メインコンポーネントのマークアップ内の最後の入力フィールドの後に
Child を追加し、
プロップとして名前を渡します:
<Child name={name} />
メインコンポーネントにインポートします:
import Child from './Child';
では、コンソールを開き、 入力フィールドに名前と名字を入力してみましょう。 ここで、名字のフィールドに文字を入力した場合でも、 子コンポーネントが毎回再描画されることがわかります。 コンポーネントが小規模であれば特に問題はありません。 しかし、このコンポーネントが大量のデータを表示し、 かつ毎回再描画されるとしたらどうでしょうか。
では、子コンポーネントを memo でラップし、
レンダリングがどのように変わるか見てみましょう。
まず、子コンポーネントに memo をインポートします:
import { memo } from 'react';
次に、新しい変数を作成し、
memo でラップされた Child を
代入します。次のような
関数式が出来上がります:
const Child = memo( function Child({ name }) {
console.log('child render');
return <h3>Hello {name}!</h3>;
});
コンソールを開き、もう一度 フィールドに名前と名字を入力してみましょう。 今度は、名字を入力しても、 子コンポーネントが再描画されないことがわかります。
ただし、これは props が変更されなくても、 コンポーネントが使用している状態が変更されたり、 変更を使用するコンテキストがある場合は 機能しないことに注意する必要があります。
このレッスンで作成した App コンポーネントのコードを基に、
最初の入力フィールドのみを残してください。
テキスト 'long text' を含む段落を持つ
React コンポーネント Text を作成し、
それを入力フィールドの後に App 内に配置してください。
Text コンポーネントに
console.log('text render'); の行を追加してください。
入力フィールドに文字を入力するたびに、
Text コンポーネントが毎回再描画されることを確認してください。
次に、Text コンポーネントを
memo でラップしてください。
入力フィールドに文字を入力しても、
Text コンポーネントが再描画されないことを確認してください。