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 に伝えるため、props と state が変更されていない限り、React は再レンダリングする必要がありません。ただし、使用しているコンテキストが変更された場合、コンポーネントは引き続き再レンダリングされます。
この例では、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} /> </> ); }