PureComponent
PureComponent
与 Component
类似,但它会跳过具有相同属性和状态的重新渲染。React 仍然支持类组件,但我们不建议在新代码中使用它们。
¥PureComponent
is similar to Component
but it skips re-renders for same props and state. Class components are still supported by React, but we don’t recommend using them in new code.
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
参考
¥Reference
PureComponent
要避免为相同的属性和状态重新渲染类组件,请扩展 PureComponent
而不是 Component
:
¥To skip re-rendering a class component for same props and state, extend PureComponent
instead of Component
:
import { PureComponent } from 'react';
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
PureComponent
是 Component
的子类,并支持 所有 Component
API。。扩展 PureComponent
相当于定义一个自定义的 shouldComponentUpdate
方法,该方法对属性和状态进行浅层比较。
¥PureComponent
is a subclass of Component
and supports all the Component
APIs. Extending PureComponent
is equivalent to defining a custom shouldComponentUpdate
method that shallowly compares props and state.
用法
¥Usage
跳过类组件不必要的重新渲染
¥Skipping unnecessary re-renders for class components
React 通常会在父级重新渲染时重新渲染组件。作为一项优化,你可以创建一个组件,只要其新的属性和状态与旧的属性和状态相同,React 就不会在其父组件重新渲染时重新渲染该组件。类组件 可以通过扩展 PureComponent
来选择此行为:
¥React normally re-renders a component whenever its parent re-renders. As an optimization, you can create a component that React will not re-render when its parent re-renders so long as its new props and state are the same as the old props and state. Class components can opt into this behavior by extending PureComponent
:
class Greeting extends PureComponent {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React 组件应该总是有 纯渲染逻辑。 这意味着如果它的属性、状态和上下文没有改变,它必须返回相同的输出。通过使用 PureComponent
,你可以告诉 React 你的组件符合此要求,因此只要其属性和状态没有改变,React 就无需重新渲染。但是,如果组件使用的上下文发生变化,它仍然会重新渲染。
¥A React component should always have pure rendering logic. This means that it must return the same output if its props, state, and context haven’t changed. By using PureComponent
, you are telling React that your component complies with this requirement, so React doesn’t need to re-render as long as its props and state haven’t changed. However, your component will still re-render if a context that it’s using changes.
在此示例中,请注意 Greeting
组件会在 name
发生更改时重新渲染(因为这是它的属性之一),但不会在 address
更改时重新渲染(因为它没有作为属性传递给 Greeting
):
¥In this example, notice that the Greeting
component re-renders whenever name
is changed (because that’s one of its props), but not when address
is changed (because it’s not passed to Greeting
as a prop):
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} /> </> ); }
备选方案
¥Alternatives
将 PureComponent
类组件从 PureComponent
迁移到函数
¥Migrating from a PureComponent
class component to a function
我们建议在新代码中使用函数组件而不是 类组件。如果你有一些使用 PureComponent
的现有类组件,你可以按照以下方法进行转换。这是原始代码:
¥We recommend using function components instead of class components in new code. If you have some existing class components using PureComponent
, here is how you can convert them. This is the original code:
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
: 调用 将此组件从类转换为函数 时
¥When you convert this component from a class to a function, wrap it in 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} /> </> ); }