MST

星途 面试题库

面试题:React 中优化动态列表性能,如何合理使用 shouldComponentUpdate 或 React.memo?

假设你正在开发一个 React 应用,其中有一个动态列表,列表项会根据用户操作动态更新。请描述如何通过 shouldComponentUpdate 方法(类组件)或 React.memo(函数组件)来优化列表的性能,防止不必要的重新渲染。同时举例说明在什么样的情况下,组件会因为数据变化而重新渲染,什么样的情况下不会。
20.9万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

类组件中使用 shouldComponentUpdate 优化

  1. 原理shouldComponentUpdate(nextProps, nextState) 方法会在组件接收到新的 props 或 state 时被调用。返回 true 表示组件需要重新渲染,返回 false 表示不需要重新渲染。通过比较当前和下一个 props 与 state,决定是否重新渲染。
  2. 示例
import React, { Component } from 'react';

class DynamicList extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    // 简单比较 props 中的某个属性,假设列表数据在 props.items 中
    if (this.props.items.length!== nextProps.items.length) {
      return true;
    }
    // 或者更复杂的比较,比如比较列表项的某个属性
    for (let i = 0; i < this.props.items.length; i++) {
      if (this.props.items[i].id!== nextProps.items[i].id) {
        return true;
      }
    }
    return false;
  }

  render() {
    return (
      <ul>
        {this.props.items.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    );
  }
}

export default DynamicList;
  1. 重新渲染情况:当 shouldComponentUpdate 返回 true 时重新渲染。比如列表项数量改变,或者列表项的关键属性(如示例中的 id)改变时。
  2. 不重新渲染情况:当 shouldComponentUpdate 返回 false 时不重新渲染。例如列表项的一些非关键属性改变,且 shouldComponentUpdate 逻辑中未对此进行判断。

函数组件中使用 React.memo 优化

  1. 原理React.memo 是一个高阶组件,它对函数组件进行了浅比较优化。它会默认比较 props,若 props 没有变化,组件不会重新渲染。
  2. 示例
import React from'react';

const DynamicList = React.memo(({ items }) => {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
});

export default DynamicList;
  1. 重新渲染情况:当 props 中的引用类型数据(如数组、对象)发生变化,即使内部数据实际未改变,也可能因为浅比较导致重新渲染。例如,创建了一个新的空数组作为 props 传递,即使数组内容和之前一样,组件也会重新渲染。
  2. 不重新渲染情况:当 props 没有变化,或者 props 中基本类型数据没有变化时,组件不会重新渲染。如果想对引用类型数据进行更深入的比较,可以传递第二个参数 areEqual 函数给 React.memo,自定义比较逻辑。例如:
import React from'react';

const areEqual = (prevProps, nextProps) => {
  if (prevProps.items.length!== nextProps.items.length) {
    return false;
  }
  for (let i = 0; i < prevProps.items.length; i++) {
    if (prevProps.items[i].id!== nextProps.items[i].id) {
      return false;
    }
  }
  return true;
};

const DynamicList = React.memo(({ items }) => {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}, areEqual);

export default DynamicList;

这样只有当列表项的 id 等关键属性变化时才会重新渲染。