React.js 中的纯组件


我们有一个生命周期方法叫做 shouldComponentUpdate,它默认返回 true(布尔值)。

shouldComponentUpdate 的目的是我们可以自定义实现默认行为,并决定 React 何时应该更新或重新渲染组件。

通常我们使用 state 或 props 值来决定更新周期。React 现在为我们提供了一个 PureComponent,它会比较 state 和 props 来决定更新周期。如果我们用 PureComponent 扩展类,则不需要重写 shouldComponentUpdate。

React 对当前 state 和 props 与新的 props 和 state 进行浅比较,以决定是否继续下一个更新周期。

这有助于提高应用程序的性能。但是,只有在比较每个 state 和 props 有意义的情况下,我们才应该用 PureComponent 扩展类。否则,如果不需要所有 state 和 props 的比较,我们可以自己实现 shouldComponentUpdate。

这个扩展 PureComponent 只适用于基于类的有状态组件。对于函数式组件,我们可以使用纯函数,如下所示:

无状态组件示例

import { pure } from ‘recompose’;
export default pure ( (props) => {
   //custom code
   return ‘something useful’ ;// your code
})

有状态组件示例

import React, {PureComponent} from ‘react’;
export default class Test extends PureComponent{
   render(){
      return ‘’;
   }
}

由于 PureComponent 对 state 和 props 对象进行浅比较,因此如果这些对象包含嵌套的数据结构,则 PureComponent 实现的 shouldComponentUpdate 将返回 false。它甚至可能跳过此组件子树的整体更新。

在这种情况下,子元素也应该是 Pure 的。

因此,嵌套数据结构的比较与 PureComponent 配合得不好。只有当 state 和 props 是简单对象时,它才有效。

如果组件在任何时候对于相同的输入值都返回相同的输出,则可以将其称为纯组件。

如果 state 或 props 引用新的对象,PureComponent 将每次都重新渲染。

应不可变地修改对象,以便使用 PureComponent 成功更新。

如果 shouldComponentUpdate 失败,我们可以使用 forceUpdate 手动重新渲染。如果我们在浅比较中嵌套了对象,可以使用 immutable.js。

示例

class Test extends React.PureComponent {
   constructor(props) {
      super(props);
      this.state = {
         taskList: [
            { title: 'excercise'},
            { title: 'cooking'},
            { title: 'Reacting'},
         ]
      };
   }
   componentDidMount() {
      setInterval(() => {
         this.setState((oldState) => {
            return { taskList: [...oldState.taskList] }
         });
      }, 1000);
   }
   render() {
      console.log(“taskList render called”);
      return (<div>
         {this.state.taskList.map((task, i) => {
            return (<Task
               key={i}
               title={task.title}
            />);
         })}
      </div>);
   }
}
class Task extends React.Component {
   render() {
      console.log(“task added”);
      return (<div>
         {this.props.title}
      </div>);
   }
}
ReactDOM.render(<Test />, document.getElementById('app'));

我们从 componentDidMount 之后每秒手动触发一次 prop 更改调用,只是为了展示每次如何渲染每个任务。

请检查浏览器控制台日志。

因为 Task 组件没有扩展 PureComponent。React不知道发生了什么变化,所以它每次都会渲染 Task。

所以现在只需用下面的代码更改 Task 组件

Export default class task extends PureComponent => 这解决了 Task 的多次渲染问题,并在没有添加新任务的情况下防止不必要的渲染。

更新于:2019年9月4日

2K+ 浏览量

启动你的职业生涯

完成课程获得认证

开始学习
广告