PureComponent
Ми рекомендуємо визначати компоненти як функції замість класів. Дивіться, як мігрувати.
PureComponent
схожий на Component
, але пропускає повторні рендеринги для тих самих пропсів та стану. Компоненти класів все ще підтримуються React, але ми не рекомендуємо використовувати їх у новому коді.
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
Довідник
PureComponent
Щоб пропустити повторний рендеринг компонента класу для тих самих пропсів та стану, розширте PureComponent
замість Component
:
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent
є підкласом Component
і підтримує всі API Component
. Розширення PureComponent
еквівалентно визначенню власного методу shouldComponentUpdate
, який неглибоко порівнює пропси та стан.
Дивіться більше прикладів нижче.
Використання
Пропуск непотрібних повторних рендерингів для компонентів класу
Зазвичай React повторно рендерить компонент, коли рендериться його батько. В якості оптимізації, ви можете створити компонент, який React не буде повторно рендерити, коли рендериться його батько, якщо його нові пропси і стан не відрізняються від старих пропсів і стану. Компоненти класу можуть обрати таку поведінку, розширивши PureComponent
:
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React-компонент завжди повинен мати чисту логіку рендерингу. Це означає, що він повинен повертати те саме виведення, якщо його пропси, стан та контекст не змінилися. Використовуючи PureComponent
, ви повідомляєте React, що ваш компонент відповідає цій вимозі, тому React не потрібно повторно рендерити, поки його пропси та стан не змінилися. Однак, ваш компонент все одно буде повторно ререндерити, якщо зміниться контекст, який він використовує.
У цьому прикладі зверніть увагу, що компонент Greeting
повторно рендериться щоразу, коли змінюється name
(оскільки це один з його пропсів), але не тоді, коли змінюється address
(оскільки він не передається Greeting
як проп):
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
до функції
У новому коді рекомендується використовувати функціональні компоненти замість класових компонентів. Якщо у вас є деякі існуючі класові компоненти, що використовують 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
не порівнює новий та старий стани. У функціональних компонентах виклик функції
set з тим самим станом вже за замовчуванням запобігає повторному рендерингу, навіть без memo
.