首页 > 解决方案 > React:如果 useCallback 返回一个值可以吗,或者这是一个不好的模式?

问题描述

我有一个名为filterContactsByValue. 它被柯里化并接受一个值和一个联系人列表,然后根据该值过滤列表并返回(新的)过滤列表。

由于列表通常很大(超过 10.000 个条目),网络应用程序应该在智能手机上运行,​​并且过滤器考虑了许多值,我想优化计算资源。因此我useDebounce习惯于不进行不必要的计算。

我也用useCallback这样的方式来记忆 的计算filteredContacts

function FilteredContacts({contacts}) {
  const [filterParam, setFilterParam] = useState('');
  const [value] = useDebounce(filterParam, 800);
  const filterContacts = filterContactsByValue(value.toLowerCase());

  // Is this okay?  ...
  const getFilteredContacts = useCallback(() => filterContacts(contacts), [
    value
  ]);

  return (
    <div className="main">
      <SearchBar
        value={filterParam}
        onChangeText={setFilterParam}
      />
      // ... and then this? 
      <ContactList contacts={getFilteredContacts()} />
    </div>
  );
}

我想知道这是否可以,或者返回这样的值是否是不好的做法。如果它不好,为什么以及如何改进它?

编辑: 功能filterContactsByValue

import { any, filter, includes, map, pick, pipe, toLower, values } from 'ramda';
import { stringFields } from './config/constants';

const contactIncludesValue = value =>
  pipe(
    pick(stringFields),
    map(toLower),
    values,
    any(includes(value))
  );

const filterContactsByValue = pipe(
  contactIncludesValue,
  filter
);

标签: reactjsreact-hooksreact-component

解决方案


简短的回答:使用useMemo代替useCallback,如下所示:

const filteredContacts = useMemo(() => filterContacts(contacts), [
    value
  ]);

...
<ContactList contacts={filteredContacts} />

为什么 ?useCallback记忆函数的创建。意思是,如果不同的参数相同,则函数的引用将相同。每次它仍然会被调用,并且在你的情况下,不会阻止任何计算。

您想要的是仅在value更改时过滤您的联系人。useMemo记住函数的最后一个返回值,并且只会在差异参数更改时重新运行。而且它们每 800 毫秒不会更改一次以上,因为您可以很好地对其进行去抖动。

PS:您可以useCallback用来防止filterContacts无缘无故地重新计算:

 const filterContacts = useCallback(() => filterContactsByValue(value.toLowerCase(), [value]);

即使在您的情况下,性能增益也很小。


推荐阅读