MST
星途 面试题库

面试题:React组件性能优化之高级难度 - memo与useCallback的结合应用

在使用React hooks的项目中,`memo` 和 `useCallback` 是优化性能的常用手段。请阐述 `memo` 和 `useCallback` 的工作原理,以及在什么场景下需要将它们结合使用。例如,有一个列表组件,列表项是可点击的,点击后会触发一个复杂的计算函数,如何利用 `memo` 和 `useCallback` 优化该组件的性能?
31.8万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

memo 工作原理

memo 是 React 提供的一个高阶组件,用于对函数式组件进行浅比较优化。当组件的 props 没有发生变化时,memo 会阻止组件重新渲染。它会对新旧 props 进行浅比较,如果浅比较结果为相等(即新旧 props 引用相同或所有一级属性的值相同),则不会触发重新渲染,从而提高性能。

useCallback 工作原理

useCallback 是一个 React Hook,它返回一个 memoized 回调函数。其原理是只有当指定的依赖项数组中的值发生变化时,才会返回新的回调函数。否则,会返回上一次缓存的回调函数引用。这样在依赖不变的情况下,回调函数的引用保持不变,有助于避免不必要的重新渲染。

结合使用场景

在以下场景下需要结合使用 memouseCallback:当一个组件接收回调函数作为 props,并且该组件被 memo 包裹以防止不必要的重新渲染时,如果回调函数每次渲染都变化,会导致 memo 失效。此时使用 useCallback 来缓存回调函数,确保其引用稳定,让 memo 能够正常工作。

列表组件优化示例

对于一个列表组件,列表项可点击且点击后触发复杂计算函数的场景,优化步骤如下:

  1. 列表项组件使用 memo
    const ListItem = React.memo(({ item, onClick }) => {
      return (
        <li onClick={() => onClick(item)}>
          {item.text}
        </li>
      );
    });
    
    这里 ListItem 组件使用 memo 包裹,当 itemonClick props 没有变化时,不会重新渲染。
  2. 父组件中使用 useCallback
    import React, { useCallback } from'react';
    import ListItem from './ListItem';
    
    const complexCalculation = (item) => {
      // 复杂计算逻辑
      return result;
    };
    
    const ListComponent = () => {
      const items = [/* 列表数据 */];
      const handleClick = useCallback((item) => {
        complexCalculation(item);
      }, []);
    
      return (
        <ul>
          {items.map((item) => (
            <ListItem key={item.id} item={item} onClick={handleClick} />
          ))}
        </ul>
      );
    };
    
    export default ListComponent;
    
    在父组件 ListComponent 中,使用 useCallback 来 memoize handleClick 回调函数。依赖项数组为空,意味着只要组件挂载,handleClick 的引用就不会改变。这样传递给 ListItemonClick prop 引用稳定,ListItemmemo 就能正常工作,避免因 onClick 变化导致的不必要渲染,从而提升性能。