PureComponent
PureComponent
は Component
と似ていますが、同じ props と state に対しては再レンダーをスキップします。クラスコンポーネントはまだ React によってサポートされていますが、新しいコードでの使用は推奨されません。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
リファレンス
PureComponent
同じ props と state に対してクラスコンポーネントの再レンダーをスキップしたい場合、Component
の代わりに PureComponent
を継承します。
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent
は Component
のサブクラスであり、すべての Component
API をサポートしています。PureComponent
を拡張することは、props と state を浅く比較するカスタムの shouldComponentUpdate
メソッドを定義することと同等です。
使用法
クラスコンポーネントの不要な再レンダーをスキップする
React は通常、親が再レンダーされるたびにコンポーネントを再レンダーします。最適化として、新しい props や state が古い props や state と同じである限り、親が再レンダーされても React が再レンダーを行わない、というコンポーネントを作成することができます。クラスコンポーネントでは、PureComponent
を継承することにより、この挙動を有効化できます。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React コンポーネントは常に純粋なレンダーロジックを持つべきです。これはすなわち、その props、state、コンテクストが変わらない場合は、常に同じ出力を返す必要がある、という意味です。PureComponent
を使用することで、あなたのコンポーネントがこの要件を満たしていると React に伝えることができ、そのため React は props と state が変わらない限り再レンダーする必要がないと判断します。ただし、使用しているコンテクストが変更された場合、コンポーネントは再レンダーされます。
以下の例で、name
が変更されるたびに Greeting
コンポーネントが再レンダーされる(name
が props として渡されているため)が、address
が変更されても再レンダーされない(Greeting
に props として渡されていないため)ことに注目してください。
import { PureComponent, useState } from 'react'; class Greeting extends PureComponent { render() { console.log("Greeting was rendered at", new Date().toLocaleTimeString()); return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>; } } export default function MyApp() { const [name, setName] = useState(''); const [address, setAddress] = useState(''); return ( <> <label> Name{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> Address{': '} <input value={address} onChange={e => setAddress(e.target.value)} /> </label> <Greeting name={name} /> </> ); }
代替手段
PureComponent
クラスのコンポーネントから関数コンポーネントへの移行
新しいコードでは、クラスコンポーネントの代わりに関数コンポーネントを使用することを推奨します。以下では、既存の PureComponent
を使用したクラスコンポーネントがある場合、どのように移行するかを説明します。こちらが元のコードです。
import { PureComponent, useState } from 'react'; class Greeting extends PureComponent { render() { console.log("Greeting was rendered at", new Date().toLocaleTimeString()); return <h3>Hello{this.props.name && ', '}{this.props.name}!</h3>; } } export default function MyApp() { const [name, setName] = useState(''); const [address, setAddress] = useState(''); return ( <> <label> Name{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> Address{': '} <input value={address} onChange={e => setAddress(e.target.value)} /> </label> <Greeting name={name} /> </> ); }
このコンポーネントをクラスから関数に移行したい場合は、memo
でラップしてください。
import { memo, useState } from 'react'; const Greeting = memo(function Greeting({ name }) { console.log("Greeting was rendered at", new Date().toLocaleTimeString()); return <h3>Hello{name && ', '}{name}!</h3>; }); export default function MyApp() { const [name, setName] = useState(''); const [address, setAddress] = useState(''); return ( <> <label> Name{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> Address{': '} <input value={address} onChange={e => setAddress(e.target.value)} /> </label> <Greeting name={name} /> </> ); }