如何在React中使用Memo(详细指南)

76 阅读3分钟

React的useMemo Hook可以用来优化你的React函数组件计算成本。我们将先通过一个组件的例子来说明这个问题,然后用React的useMemo Hook来解决这个问题。

请记住,React中的大部分性能优化都是不成熟的。React的默认速度很快,所以每一个性能优化都是选择的,以防某些东西开始感觉到慢。

注意:不要把React的useMemo Hook和React的memo API搞错。useMemo是用来记忆数值的,而React memo是用来包装React组件以防止重新渲染的。

注意:不要把React的useMemo Hook和React的useCallback Hook搞错。useMemo是用来记忆值的,而useCallback是用来记忆函数的。

让我们来看看下面这个React应用程序的例子,它渲染了一个用户列表,并允许我们通过他们的名字来过滤用户。陷阱。只有当用户明确地点击一个按钮时,过滤才会发生;而不是当用户在输入框中输入时才发生。

import React from 'react';

const users = [
  { id: 'a', name: 'Robin' },
  { id: 'b', name: 'Dennis' },
];

const App = () => {
  const [text, setText] = React.useState('');
  const [search, setSearch] = React.useState('');

  const handleText = (event) => {
    setText(event.target.value);
  };

  const handleSearch = () => {
    setSearch(text);
  };

  const filteredUsers = users.filter((user) => {
    return user.name.toLowerCase().includes(search.toLowerCase());
  });

  return (
    <div>
      <input type="text" value={text} onChange={handleText} />
      <button type="button" onClick={handleSearch}>
        Search
      </button>

      <List list={filteredUsers} />
    </div>
  );
};

const List = ({ list }) => {
  return (
    <ul>
      {list.map((item) => (
        <ListItem key={item.id} item={item} />
      ))}
    </ul>
  );
};

const ListItem = ({ item }) => {
  return <li>{item.name}</li>;
};

export default App;

即使filteredUsers ,当有人在输入框中输入时也不会发生变化,因为它们只在通过search 状态点击按钮时发生变化,过滤器的回调函数在输入框中的每一次击键都会重复运行。

function App() {
  ...

  const filteredUsers = users.filter((user) => {
    console.log('Filter function is running ...');
    return user.name.toLowerCase().includes(search.toLowerCase());
  });

  ...
}

这并没有减慢这个小型React应用程序的速度。然而,如果我们要处理这个数组中的大量数据,并为每个按键运行过滤器的回调函数,我们也许会拖慢应用程序。因此,你可以使用React的useMemo Hook来记忆一个函数的返回值,并且只在函数的依赖关系(这里是search )发生变化时才运行。

function App() {
  ...

  const filteredUsers = React.useMemo(
    () =>
      users.filter((user) => {
        console.log('Filter function is running ...');
        return user.name.toLowerCase().includes(search.toLowerCase());
      }),
    [search]
  );

  ...
}

现在,这个函数只在search 状态改变时才被执行。如果text 状态发生变化,它就不会运行,因为这不是这个过滤函数的依赖项,因此不是useMemo钩子的依赖项数组中的依赖项。自己试试吧。在输入框中输入一些东西应该不会触发记录,但通过点击按钮执行搜索会触发记录。


毕竟,你可能想知道为什么你不在所有的值计算中使用React的useMemo Hook,或者为什么React的useMemo Hook不是所有值计算的默认值。在内部,React的useMemo Hook必须在每次重新渲染时比较依赖数组中的依赖关系,以决定它是否应该重新计算值。通常情况下,这种比较的计算可能比重新计算数值更昂贵。总之,React的useMemo Hook是用来记忆值的。