MST

星途 面试题库

面试题:React 条件渲染下的重渲染性能优化策略

假设你正在开发一个复杂的 React 组件,组件内部存在多层嵌套的条件渲染逻辑,并且这些条件渲染依赖于父组件传递的 props 以及组件自身的 state。在开发过程中,你发现组件频繁重渲染,导致性能下降。请详细阐述如何通过 React.memo、useMemo、useCallback 等工具结合条件渲染逻辑来优化性能,并举例说明这些工具在不同场景下的具体应用。
46.1万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. React.memo

  • 作用:React.memo 是一个高阶组件,用于对函数式组件进行浅比较优化。它会在组件接收到新的 props 时,对新旧 props 进行浅比较,如果 props 没有变化,组件就不会重新渲染。
  • 应用场景:适用于纯展示型组件,即组件的渲染结果只依赖于 props,不依赖于自身的 state 或者上下文环境等其他因素。
  • 示例
import React from'react';

const MyComponent = React.memo((props) => {
  return <div>{props.value}</div>;
});

export default MyComponent;

在上述示例中,MyComponent 是一个展示 props.value 的组件。使用 React.memo 后,只有当 props.value 发生变化时,组件才会重新渲染。

2. useMemo

  • 作用useMemo 用于缓存一个值(通常是一个计算结果),只有当它的依赖项发生变化时才会重新计算。它可以避免在每次渲染时都进行不必要的计算,从而提升性能。
  • 应用场景:当你有一个复杂的计算,而这个计算结果在某些依赖项没有变化时不需要重新计算的场景。例如,计算一个数组的总和,而数组本身没有变化,就不需要每次渲染都重新计算总和。
  • 示例
import React, { useMemo } from'react';

const MyComponent = ({ largeArray }) => {
  const sum = useMemo(() => {
    return largeArray.reduce((acc, num) => acc + num, 0);
  }, [largeArray]);

  return <div>{`Sum: ${sum}`}</div>;
};

export default MyComponent;

在这个例子中,useMemo 缓存了 largeArray 的总和计算结果。只有当 largeArray 发生变化时,才会重新计算 sum

3. useCallback

  • 作用useCallback 用于缓存一个函数,只有当它的依赖项发生变化时才会重新创建函数。这在将函数作为 props 传递给子组件,并且希望避免子组件不必要的重新渲染时非常有用。
  • 应用场景:常见于子组件依赖父组件传递的函数,且该函数内部逻辑在组件多次渲染过程中不会改变的场景。比如父组件传递一个点击处理函数给子组件,使用 useCallback 可以确保只有依赖项变化时才重新创建该函数,避免子组件因函数引用变化而不必要地重新渲染。
  • 示例
import React, { useCallback } from'react';

const ChildComponent = ({ onClick }) => {
  return <button onClick={onClick}>Click me</button>;
};

const ParentComponent = () => {
  const handleClick = useCallback(() => {
    console.log('Button clicked');
  }, []);

  return <ChildComponent onClick={handleClick} />;
};

export default ParentComponent;

在上述代码中,ParentComponent 使用 useCallback 缓存了 handleClick 函数。只要依赖项数组 [] 中的值没有变化,handleClick 的引用就不会改变,从而避免 ChildComponent 因函数引用变化而不必要地重新渲染。

结合条件渲染逻辑优化性能

假设我们有一个复杂的 React 组件,内部存在多层嵌套的条件渲染逻辑,依赖于 props 和 state。

import React, { useState, useMemo, useCallback } from'react';

const ComplexComponent = ({ data }) => {
  const [filter, setFilter] = useState('all');

  const filteredData = useMemo(() => {
    if (filter === 'all') {
      return data;
    } else {
      return data.filter(item => item.type === filter);
    }
  }, [data, filter]);

  const handleFilterChange = useCallback((newFilter) => {
    setFilter(newFilter);
  }, []);

  return (
    <div>
      <select onChange={(e) => handleFilterChange(e.target.value)}>
        <option value="all">All</option>
        <option value="type1">Type 1</option>
        <option value="type2">Type 2</option>
      </select>
      {filteredData.map(item => (
        <div key={item.id}>
          {item.name} - {item.type}
        </div>
      ))}
    </div>
  );
};

export default ComplexComponent;

在这个 ComplexComponent 中:

  • useMemo 用于缓存 filteredData 的计算结果,只有当 data 或者 filter 变化时才重新计算。
  • useCallback 用于缓存 handleFilterChange 函数,避免因函数引用变化导致 select 组件不必要的重新渲染。这样结合条件渲染逻辑,有效地提升了组件性能。