react useMemo

发布时间 2023-04-11 16:53:17作者: wenwen。

useMemo 是 React 提供的一个用于优化组件性能的钩子函数。它可以缓存组件的计算结果,并在依赖项发生变化时重新计算。这可以避免在每次组件渲染时都重新计算相同的值,从而提高组件的性能。

useMemo 的语法如下:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

其中,computeExpensiveValue 是一个计算函数,它会在组件渲染时调用,并返回需要缓存的值。ab 是计算函数的依赖项,当依赖项发生变化时,useMemo 会重新计算缓存的值。

使用 useMemo 的一个常见场景是在渲染大量数据时进行性能优化。例如,在渲染一个表格时,我们可能需要根据表格的数据进行一些复杂的计算,如计算每行数据的总和、平均值等。如果在每次渲染时都进行这些计算,会导致页面的响应变慢。使用 useMemo 可以缓存这些计算结果,并在数据发生变化时重新计算,从而提高页面的性能。

下面是一个使用 useMemo 的示例,该示例计算一个数组的总和:

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

function App() {
  const [numbers, setNumbers] = useState([1, 2, 3, 4, 5]);

  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return numbers.reduce((acc, val) => acc + val, 0);
  }, [numbers]);

  return (
    <div>
      <p>Numbers: {numbers.join(', ')}</p>
      <p>Sum: {sum}</p>
      <button onClick={() => setNumbers([...numbers, Math.floor(Math.random() * 10)])}>
        Add Number
      </button>
    </div>
  );
}

export default App;

在上面的示例中,我们使用 useMemo 缓存了数组 numbers 的总和。当 numbers 发生变化时,useMemo 会重新计算总和。这样,我们就避免了在每次渲染时都重新计算总和的操作,从而提高了组件的性能。

需要注意的是,useMemo 的缓存值并不会在组件的多次渲染之间共享。每次渲染都会调用计算函数,并返回一个新的缓存值。因此,我们应该避免将 useMemo 的结果用作可变对象的引用,而应该将其用作值类型的数据。如果需要缓存可变对象,应该使用其他的缓存方案。

下面是一个使用 useMemo 优化表格组件性能的示例:

import React, { useMemo } from 'react';

function Table(props) {
  const { data } = props;

  const columns = useMemo(
    () => [
      {
        Header: 'ID',
        accessor: 'id',
      },
      {
        Header: 'Name',
        accessor: 'name',
      },
      {
        Header: 'Age',
        accessor: 'age',
      },
      {
        Header: 'Email',
        accessor: 'email',
      },
    ],
    []
  );

  const tableData = useMemo(() => {
    console.log('Computing table data...');
    return data.map((row) => ({
      id: row.id,
      name: row.name,
      age: row.age,
      email: row.email,
    }));
  }, [data]);

  return (
    <table>
      <thead>
        <tr>
          {columns.map((column) => (
            <th key={column.Header}>{column.Header}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {tableData.map((row) => (
          <tr key={row.id}>
            <td>{row.id}</td>
            <td>{row.name}</td>
            <td>{row.age}</td>
            <td>{row.email}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

export default Table;

在上面的示例中,我们使用了两个 useMemo 钩子函数:一个用于缓存表格的列定义,另一个用于缓存表格的数据。

在表格中,每次渲染都需要进行列的定义和数据的处理。由于这些操作可能比较耗时,因此我们可以使用 useMemo 缓存它们的结果。在第一次渲染时,useMemo 会计算出缓存的结果,并在后续渲染中直接使用缓存的结果,从而避免了重复计算的开销。

需要注意的是,我们在 useMemo 中指定了依赖项,以便在依赖项发生变化时重新计算缓存的结果。对于第一个 useMemo,我们没有指定任何依赖项,因为表格的列定义是静态的,不会随着时间的推移而改变。对于第二个 useMemo,我们指定了 data 作为依赖项,因为表格的数据可能会随着用户的操作而改变。

这样,我们就使用了 useMemo 钩子函数来优化表格组件的性能,从而提高了应用程序的响应速度。