「React」中避免组件重复渲染

633 阅读1分钟

React 避免组件重复渲染,通常是最重要的代码层面的前端优化手段之一,关键在于开发者对应用的关键之处进行特殊处理,比如父组件状态更新导致无关的子组件重新渲染,从而避免 React reconciler调和昂贵的性能开销。

栗子

一个具有状态的列表,子组件ListItem的事件出发之后,会导致父组件状态listData变更。

import React from "react";

const initListData = Array.from(Array(10), (v, i) => {
  return { text: i, id: i };
});

// Chidren
const ListItem = ({ text, id, onRemove }) => {
  console.log("listitem");
  return (
    <li>
      <span>{text}</span>
      <button onClick={() => onRemove(id)}>删除</button>
    </li>
  );
};

// Parent
export default class App extends React.Component {
  state = {
    listData: initListData
  };

  handleRemove = (id) => {
    const { listData } = this.state;
    this.setState({ listData: listData.filter((v, k) => v.id !== id) });
  };

  render() {
    const { listData } = this.state;
    return (
      <ul>
        {listData.map(({ text, id }, index) => (
          <ListItem key={id} id={id} text={text} onRemove={(id) => this.handleRemove(id)} />
        ))}
      </ul>
    );
  }
}

1. React.Memo

函数组件写法:当且仅当 text, id, onRemove 改变时,子组件触发重新渲染。

const ListItem = React.memo(({ text, id, onRemove }) => {
  console.log("listitem");
  return (
    <li>
      <span>{text}</span>
      <button onClick={() => onRemove(id)}>删除</button>
    </li>
  );
});

2. React.PureComponent

类组件写法:当且仅当 text, id, onRemove 改变时,子组件触发重新渲染。

class ListItem extends React.PureComponent {
  render() {
    const { text, id, onRemove } = this.props;
    console.log("listitem");
    return (
      <li>
        <span>{text}</span>
        <button onClick={() => onRemove(id)}>删除</button>
      </li>
    );
  }
}

3. shouldComponentUpdate

类组件写法:当且仅当 text, id, onRemove 改变时,子组件触发重新渲染。

class ListItem extends React.Component {
  shouldComponentUpdate(preprops, nextprops) {
    // deep diff
  }
  
  render() {
    const { text, id, onRemove } = this.props;
    console.log("listitem");
    return (
      <li>
        <span>{text}</span>
        <button onClick={() => onRemove(id)}>删除</button>
      </li>
    );
  }
}

4. JSX 中移除箭头函数

由于箭头函数会生成新的引用,

避免使用箭头函数 onRemove={(id) => this.handleRemove(id)}

<ListItem key={id} id={id} text={text} onRemove=(id) => this.handleRemove(id)} />

推荐使用类属性 onRemove={this.handleRemove}

<ListItem key={id} id={id} text={text} onRemove={this.handleRemove} />

5. Immutable.js 不可变数据结构

github.com/immutable-j…