React - React.Component 存在的问题及优化(React.PureComponent 的使用)

react 官网:https://zh-hans.reactjs.org/docs/react-api.html#reactcomponent

一. React.Component 与 React.PureComponent

  1. React.PureComponentReact.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 propstate 的方式来实现了该函数。
  2. 如果赋予 React 组件相同的 propsstaterender() 函数会渲染相同的内容,那么在某些情况下使用 React.PureComponent 可提高性能。
  3. React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果。仅在你的 propsstate 较为简单时,才使用 React.PureComponent,或者在深层数据结构发生变化时调用 forceUpdate() 来确保组件被正确地更新。你也可以考虑使用 immutable 对象加速嵌套数据的比较。
  4. 此外,React.PureComponent 中的 shouldComponentUpdate() 将跳过所有子组件树的 prop 更新。因此,请确保所有子组件也都是“纯”的组件。

二. React.Component 存在的问题

  1. 两个问题:
    1. 只要执行 setState(),即使不改变状态数据, 组件也会重新 render()
    2. 只要当前组件重新 render(), 就会自动重新 render() 子组件,即使子组件没有用到父组件的任何数据。
  2. 原因:

    Component 中的 shouldComponentUpdate() 总是返回 true

  3. 解决思路:

    只有当组件的 stateprops 数据发生改变时才重新 render()

三. 解决(优化)方法

  1. 重写 shouldComponentUpdate() 方法

    比较新旧 stateprops 数据, 如果有变化才返回 true , 如果没有返回 false

    shouldComponentUpdate(nextProps, nextState) {
      console.log(this.props, this.state); //当前的props和state
      console.log(nextProps, nextState); //将要变化的 目标props 和 目标state
      if (
        JSON.stringify(this.state) === JSON.stringify(nextState) &&
        JSON.stringify(this.props) === JSON.stringify(nextProps)
      ) {
        return false;
      } else {
        return true;
      }
    }
    
  2. 使用 React.PureComponent
    import React, { PureComponent } from "react";
    
    export default class index extends PureComponent {
      render() {
        return <div>index</div>;
      }
    }
    

四. 解决(优化)组件实例

this.setState() 真实修改假修改 状态,对比 render() 中是否会打印

  1. 重写 shouldComponentUpdate() 方法

    import React, { Component } from "react";
    
    export default class Parent extends Component {
      state = {
        count: 10,
      };
      shouldComponentUpdate(nextProps, nextState) {
        if (
          JSON.stringify(this.state) === JSON.stringify(nextState) &&
          JSON.stringify(this.props) === JSON.stringify(nextProps)
        ) {
          return false;
        } else {
          return true;
        }
      }
      increment = () => {
        // 假修改
        this.setState({});
        // 真实修改
        // this.setState({
        //   count: this.state.count + 1,
        // });
      };
      render() {
        console.log("Parent_render"); //查看控制台是否打印
        const { count } = this.state;
        return (
          <div>
            <h2>Parent组件</h2>
            <span>数值为:{count}</span>
            <br />
            <button onClick={this.increment}>+1</button>
            <Child count={count} />
          </div>
        );
      }
    }
    
    class Child extends Component {
      shouldComponentUpdate(nextProps, nextState) {
        if (
          JSON.stringify(this.state) === JSON.stringify(nextState) &&
          JSON.stringify(this.props) === JSON.stringify(nextProps)
        ) {
          return false;
        } else {
          return true;
        }
      }
      render() {
        console.log("child_render"); //查看控制台是否打印
        const { count } = this.props;
        return (
          <div>
            <h2>Child组件</h2>
            <span>Parent组件的数值是:{count}</span>
          </div>
        );
      }
    }
    
  2. 使用 React.PureComponent

    import React, { PureComponent } from "react";
    
    export default class Parent extends PureComponent {
      state = {
        count: 10,
      };
      increment = () => {
        // 假修改
        this.setState({});
        // 真实修改
        // this.setState({
        //   count: this.state.count + 1,
        // });
      };
      render() {
        console.log("Parent_render"); //查看控制台是否打印
        const { count } = this.state;
        return (
          <div>
            <h2>Parent组件</h2>
            <span>数值为:{count}</span>
            <br />
            <button onClick={this.increment}>+1</button>
            <Child count={count} />
          </div>
        );
      }
    }
    
    class Child extends PureComponent {
      render() {
        console.log("child_render"); //查看控制台是否打印
        const { count } = this.props;
        return (
          <div>
            <h2>Child组件</h2>
            <span>Parent组件的数值是:{count}</span>
          </div>
        );
      }
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值