title |
---|
PureComponent |
クラスの代わりに関数でコンポーネントを定義することを推奨します。移行方法はこちら。
PureComponent
は Component
と似ていますが、同じ props と state に対しては再レンダーをスキップします。クラスコンポーネントはまだ React によってサポートされていますが、新しいコードでの使用は推奨されません。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
同じ 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} />
</>
);
}
label {
display: block;
margin-bottom: 16px;
}
クラスの代わりに関数でコンポーネントを定義することを推奨します。移行方法はこちら。
PureComponent
クラスのコンポーネントから関数コンポーネントへの移行 {/migrating-from-a-purecomponent-class-component-to-a-function/}
新しいコードでは、クラスコンポーネントの代わりに関数コンポーネントを使用することを推奨します。以下では、既存の 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} />
</>
);
}
label {
display: block;
margin-bottom: 16px;
}
このコンポーネントをクラスから関数に移行したい場合は、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} />
</>
);
}
label {
display: block;
margin-bottom: 16px;
}
PureComponent
とは異なり、memo
は新旧の state を比較しません。関数コンポーネントでは、同一の state 値で set
関数を呼び出した場合、memo
がなくてもデフォルトで再レンダーが防止されます。