Skip to content

优化前的代码

默认情况下, react 在修改父组件的 state 时, 子组件无论是否有变化, 都会重新渲染, 这就不合理

jsx
import React from "react";

class Child extends React.Component {
  render() {
    console.info("Child 组件渲染了");
    return <div>子组件: {this.props.age}</div>;
  }
}

class App extends React.Component {
  state = {
    name: "app",
    age: 10,
  };

  render() {
    console.info("App 组件渲染了");
    return (
      <div>
        <div>
          <p>{this.state.name} </p>
          <button onClick={() => this.setName()}>修改不影响子组件的数据</button>
        </div>
        <div>
          <p>{this.state.age}</p>
          <button onClick={() => this.setAge()}>修改会影响子组件的数据</button>
        </div>

        <Child age={this.state.age} />
      </div>
    );
  }

  setName() {
    this.setState({
      name: "name被修改了",
    });
  }

  setAge() {
    this.setState({
      age: 20,
    });
  }
}

export default App;

!> 上面代码执行和测试结果可知, 修改父组件 state 是, 无论是否影响子组件, 子组件都会被重新渲染

使用 shouldComponentUpdate 优化

  • 使用这种方法优化的缺点就是, 需要自己去判断每个状态是否改变
jsx
class Child extends React.Component {
  // 该方法有3个参数:
  // 1. nextProps: 最新的props数据 2. nextState:最新的state数据 3.nextCxt: 最新的 Context 数据
  // 该方法必须返回一个 bool 值:
  // 如果返回 true 表示需要重新渲染, false 则不需要重新渲染
  shouldComponentUpdate(nextProps, nextState, nextCxt) {
    // 如果当前的 props 和最新的 props 不一致, 就更新组件
    return this.props.age !== nextProps.age;
  }

  render() {
    console.info("Child 组件渲染了");
    return <div>子组件: {this.props.age}</div>;
  }
}

使用 PureComponent 优化(推荐)

  • 这个组件是基于 shouldComponentUpdate 实现的, 但是好处就是, 不需要自己控制状态是否更新
jsx
class Child extends React.PureComponent {
  render() {
    console.info("Child 组件渲染了");
    return <div>子组件: {this.props.age}</div>;
  }
}

优化注意点

!> 不要直接修改 state 的值, 直接修改 state 的值, 会让 shouldComponentUpdate 传递的参数不正确, 无法正确的判断

jsx
class App extends React.PureComponent {
  state = {
    age: 10,
  };

  render() {
    console.info("App 组件渲染了");
    return (
      <div>
        <div>
          <p>{this.state.age}</p>
          <button onClick={() => this.setAge()}>修改会影响子组件的数据</button>
        </div>
      </div>
    );
  }

  setName() {
    this.setState({
      name: "name被修改了",
    });
  }

  setAge() {
    // 正确的写法: this.setState({age: 20});
    // 如果组件继承的是 PureComponent, 这样是无法修改的状态的
    this.state.age += 10;
    this.setState(this.state);
  }
}

优化函数式组件

不管是通过 shouldComponentUpdate 的方式, 还是通过 PureComponent 都是无法优化 函数式组件 的, 要想优化函数函数式组件, 就必须使用 memo

jsx
import React from "react";

// 位优化前的写法:
// function Child(props) {
//   console.info("Child 组件渲染了");
//   return <div>子组件: {props.age}</div>;
// }

const Child = React.memo((props) => {
  console.info("Child 组件渲染了");
  return <div>子组件: {props.age}</div>;
});

class App extends React.Component {
  state = {
    name: "app",
    age: 10,
  };

  render() {
    console.info("App 组件渲染了");
    return (
      <div>
        <div>
          <p>{this.state.name} </p>
          <button onClick={() => this.setName()}>修改不影响子组件的数据</button>
        </div>
        <div>
          <p>{this.state.age}</p>
          <button onClick={() => this.setAge()}>修改会影响子组件的数据</button>
        </div>

        <Child age={this.state.age} />
      </div>
    );
  }

  setName() {
    this.setState({
      name: "name被修改了",
    });
  }

  setAge() {
    this.setState({
      age: 20,
    });
  }
}

export default App;

Released under the MIT License.