PureComponent
PureComponent
类似于 Component
,但它会跳过对相同 props 和 state 的重新渲染。React 仍然支持类组件,但我们不建议在新代码中使用它们。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
参考
PureComponent
要跳过对相同 props 和 state 的类组件重新渲染,请扩展 PureComponent
而不是 Component
:
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent
是 Component
的子类,并支持 所有 Component
APIs。 扩展 PureComponent
等同于定义一个自定义的 shouldComponentUpdate
方法,该方法会浅比较 props 和 state。
用法
跳过类组件不必要的重新渲染
React 通常会在其父组件重新渲染时重新渲染组件。作为优化,您可以创建一个组件,只要其新的 props 和 state 与旧的 props 和 state 相同,React 就不会在父组件重新渲染时重新渲染该组件。 类组件 可以通过扩展 PureComponent
来选择这种行为。
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React 组件应始终具有纯渲染逻辑。 这意味着如果其 props、状态和上下文没有改变,它必须返回相同的输出。通过使用PureComponent
,你告诉 React 你的组件符合此要求,因此只要其 props 和状态没有改变,React 就无需重新渲染。但是,如果它正在使用的上下文发生变化,你的组件仍然会重新渲染。
在这个例子中,请注意Greeting
组件会在name
改变时重新渲染(因为这是它的一个 prop),但不会在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> 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} /> </> ); }