MST
星途 面试题库

面试题:在 React 动态列表中,如何结合 useCallback 和 useMemo 优化性能?

给定一个 React 函数组件,其中包含一个动态列表,列表项需要绑定点击事件。并且列表项的数据来源于父组件传递的 props 以及组件内部的 state。请详细阐述如何使用 useCallback 和 useMemo 来优化该动态列表的性能,避免不必要的重新计算和重新渲染。同时说明 useCallback 和 useMemo 在这种场景下的作用原理及它们之间的区别。
31.6万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

使用 useCallbackuseMemo 优化动态列表性能

  1. useCallback 优化点击事件回调

    • 在 React 函数组件中,当动态列表项绑定点击事件时,使用 useCallback 来包裹事件处理函数。
    • 示例代码如下:
    import React, { useCallback, useState } from'react';
    
    const MyList = ({ data }) => {
      const [selectedItem, setSelectedItem] = useState(null);
    
      const handleClick = useCallback((item) => {
        setSelectedItem(item);
      }, []);
    
      return (
        <ul>
          {data.map((item) => (
            <li key={item.id} onClick={() => handleClick(item)}>
              {item.name}
            </li>
          ))}
        </ul>
      );
    };
    
    export default MyList;
    
    • 原理useCallback 返回一个记忆化的回调函数。只有当依赖数组中的值发生变化时,才会重新创建这个回调函数。在上述代码中,依赖数组为空 [],意味着只要组件渲染,handleClick 函数就不会改变。这样,当列表项重新渲染时,由于点击事件回调函数没有变化,就不会触发不必要的重新渲染。
  2. useMemo 优化列表项数据计算

    • 如果列表项的数据需要进行一些复杂计算,且依赖于组件内部的 state 或父组件传递的 props,可以使用 useMemo 来缓存计算结果。
    • 示例代码如下:
    import React, { useCallback, useMemo, useState } from'react';
    
    const MyList = ({ data }) => {
      const [filterText, setFilterText] = useState('');
    
      const filteredData = useMemo(() => {
        return data.filter((item) => item.name.includes(filterText));
      }, [data, filterText]);
    
      const handleClick = useCallback((item) => {
        setFilterText(item.name);
      }, []);
    
      return (
        <div>
          <input
            type="text"
            value={filterText}
            onChange={(e) => setFilterText(e.target.value)}
          />
          <ul>
            {filteredData.map((item) => (
              <li key={item.id} onClick={() => handleClick(item)}>
                {item.name}
              </li>
            ))}
          </ul>
        </div>
      );
    };
    
    export default MyList;
    
    • 原理useMemo 会在其依赖数组中的值发生变化时,重新计算并返回缓存的值。在上述代码中,只有当 datafilterText 发生变化时,filteredData 才会重新计算,避免了不必要的重复计算,提升了性能。

useCallbackuseMemo 的区别

  1. 返回值类型
    • useCallback 返回一个记忆化的回调函数,主要用于缓存函数引用,避免函数重新创建导致的不必要渲染。
    • useMemo 返回一个记忆化的值,用于缓存复杂计算的结果,避免重复计算。
  2. 应用场景
    • useCallback 适用于需要将函数作为 prop 传递给子组件,且希望在父组件重新渲染时保持函数引用不变的场景,如动态列表的点击事件处理函数。
    • useMemo 适用于需要进行复杂计算,且计算结果依赖于某些变量,希望避免不必要的重复计算的场景,如动态列表数据的过滤、排序等计算。