React.PureComponent
和 React.memo()
都是用来控制组件的重新渲染的,用于优化性能。
React.PureComponent
适用于类组件, React.memo()
适用于函数组件。
React.PureComponent
:
React.Component
有两个问题:
- 只要执行
setState()
,即使不改变 state 状态数据,组件也会重新render()
。 - 只要当前组件重新
render()
,子组件就会自动重新render()
,即使子组件中的 props 数据没有改变或者根本就没有用到父组件的任何数据。
class Parent extends React.Component {
state = {
message:'Hello,React'
}
handleClick = () => {
// 执行了 setState(),虽然 message 的值没有改变,但 Parent 组件也会重新 render();Child 子组件虽然没有用到 Parent 组件的任何数据,但 Child 子组件也会重新 render()
this.setState({message: 'Hello,React'})
}
render() {
console.log('Parent render')
return (
<>
<h1 onClick={this.handleClick}>{this.state.message}</h1>
<Child />
</>
)
}
}
class Child extends React.Component {
render() {
console.log('Child render')
return <h2>这是 Child 组件</h2>
}
}
造成这种现象的原因是 React.Component
中的 shouldComponentUpdate()
总是返回 true。如果想要效率高,应该只有当组件的 state 或 props 数据发生变化时才重新 render()
。
React.PureComponent
重写了 shouldComponentUpdate()
方法,只有 state 或 props 数据有变化才返回 true,才会重新执行 render()
方法。
React.PureComponent
内部通过 shallowEqual()
方法对要更新的 state/props 和旧的 state/props 做了一层浅比较。对于其中的基本类型数据,只比较值;对于其中的引用类型数据,直接比较地址是否相同,不管里面内容变不变,只要地址一样,就认为没变。
class Parent extends React.PureComponent {
state = {
message:'Hello,React'
}
handleClick = () => {
// 虽然执行了 setState(),但是因为要更新的 state 中的 message 和旧的 state 中的 messafe 的值一样,所以 Parent 组件和 Child 子组件都不会重新 render()
this.setState({message: 'Hello,React'})
}
render() {
console.log('Parent render')
return (
<>
<h1 onClick={this.handleClick}>{this.state.message}</h1>
<Child />
</>
)
}
}
class Child extends React.PureComponent {
render() {
console.log('Child render')
return <h2>这是 Child 组件</h2>
}
}
React.memo()
:
class Parent extends React.Component {
state = {
message:'Hello,React'
}
handleClick = () => {
// 即使传入 Child 子组件中的 message 没有任何变化,Child 子组件也会重新 render()
this.setState({message: 'Hello,React'})
}
render() {
const {message} = this.state
return (
<>
<h1 onClick={this.handleClick}>{message}</h1>
<Child message={message} />
</>
)
}
}
const Child = (props) => {
console.log('Child render')
return (
<>
<h2>这是 Child 组件</h2>
{props.message}
</>
)
}
export default Child
React.memo()
是一个高阶函数,可以控制函数组件仅在它的 props 发生改变的时候进行重新渲染。有两个参数,第一个参数是一个纯函数的组件,第二个参数是一个函数,用于对比 props 控制是否刷新,与 shouldComponentUpdate()
功能类似。
class Parent extends React.Component {
state = {
message:'Hello,React'
}
handleClick = () => {
// 传入 Child 子组件中的 message 没有任何变化,Child 子组件不会重新 render()
this.setState({message: 'Hello,React'})
}
render() {
const {message} = this.state
return (
<>
<h1 onClick={this.handleClick}>{message}</h1>
<Child message={message} />
</>
)
}
}
const Child = (props) => {
console.log('Child render')
return (
<>
<h2>这是 Child 组件</h2>
{props.message}
</>
)
}
export default React.memo(Child)