PureComponent
PureComponent 类似于 Component,但它会跳过 props 和 state 相同情况下的重新渲染。React 仍然支持类组件,但我们不建议在新代码中使用它们。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}Reference
PureComponent
要在 props 和 state 相同的情况下跳过类组件的重新渲染,请扩展 PureComponent 而不是 Component:
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}PureComponent 是 Component 的子类,并支持 Component 的所有 API。 扩展 PureComponent 等同于定义一个自定义的 shouldComponentUpdate 方法,该方法会对 props 和 state 进行浅比较。
Usage
跳过类组件不必要的重新渲染
React 通常会在父组件重新渲染时重新渲染组件。作为一种优化,你可以创建一个组件,只要它的新 props 和 state 与旧的 props 和 state 相同,React 就不会在其父组件重新渲染时重新渲染它。类组件 可以通过扩展 PureComponent 来选择启用这种行为:
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}React 组件应该始终具有纯渲染逻辑。 这意味着如果它的 props、state 和 context 没有改变,它必须返回相同的输出。通过使用 PureComponent,你是在告诉 React 你的组件符合这一要求,因此只要它的 props 和 state 没有改变,React 就不需要重新渲染它。不过,如果它使用的某个 context 发生变化,你的组件仍然会重新渲染。
在这个示例中,注意 Greeting 组件会在 name 变化时重新渲染(因为它是其 props 之一),但在 address 变化时不会重新渲染(因为它没有作为 prop 传给 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> 姓名{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> 地址{': '} <input value={address} onChange={e => setAddress(e.target.value)} /> </label> <Greeting name={name} /> </> ); }
Alternatives
将 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> 姓名{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> 地址{': '} <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> 姓名{': '} <input value={name} onChange={e => setName(e.target.value)} /> </label> <label> 地址{': '} <input value={address} onChange={e => setAddress(e.target.value)} /> </label> <Greeting name={name} /> </> ); }