React中render函数被持续调用的优化

284 阅读2分钟

我们先来看一个例子:

1668834619098.png

App有一个counter计数器,同时还有子组件Home,当点击按钮+1后,App的render函数会被调用,但同时我们发现Home组件的render函数也被调用了10次。

那么,我们思考一下,在以后的开发中,我们只要是修改了App中的数据,所有的组件都需要重新render,进行diff算法,那性能必然是很低的。

  • 实际上,很多组件没有必要重新调用render函数
  • 他们调用render函数应该有一个前提,就是依赖的数据(state、props) 发生改变时才调用。

那么如何来进行优化呢?

一、使用shouldComponentUpdate方法进行优化

  • React的生命周期方法shouldComponentUpdate,这个方法接受参数,并且需要有返回值:

  • 该方法有两个参数:

    • 参数一:nextProps修改之后,最新的props属性
    • 参数二:nextState修改之后,最新的state属性
  • 该方法返回值时是一个boolean类型:

    • 返回值为true,那么就需要调用render方法
    • 返回值为false,那么就不需要调用render方法
    • 默认返回的是true

下面的例子中,在子组件中增加一个shouldComponentUpdate方法来优化调用render

Home组件render函数只有在初次渲染的时候调用了一次,后面counter发生改变的时候,render函数并被没有调用。

class Home extends Component {
  shouldComponentUpdate(nextProps,nextState){
    if(this.props.name !== nextProps.name) {
      return true;
    }
    return false;
  }
  render() {
    const {name} = this.props;
    console.log("Home组件的render函数,组件被渲染了");
    return <div><h2>Home Page</h2><h3>我的名字:{name}</h3></div>;
  }
}
​
class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'kobe',
      counter: 100
    };
  }
  render() {
    const { name,counter } = this.state;
    return (
      <div>
        <h2>App page: { counter } </h2>
        <button onClick={e=> this.setState({counter: counter+1}) }>+1</button>
        <hr />
        <Home name={name}></Home>
      </div>
    );
  }
}

1668932895168.png

二、PureComponent

如果所有的类,我们都需要手动来实现shouldComponentUpdate,那么会给我们开发者增加非常多的工作量。**

可以考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。

三、高阶组件memo

const Home = memo((props) => {
  const { name } = props;
  console.log("Home组件的render函数,组件被渲染了");
  return (
    <div>
      <h2>Home Page</h2>
      <h3>我的名字:{name}</h3>
    </div>
  );
});

函数式组件在props没有改变时,也是不希望其重新渲染其DOM树结构的。