代码之家  ›  专栏  ›  技术社区  ›  J. Hesters

反应:如果useCallback返回一个值可以吗,或者这是一个错误的模式?

  •  0
  • J. Hesters  · 技术社区  · 7 年前

    我有一个函数叫做 filterContactsByValue . 它是咖喱的,接受一个值和一个联系人列表,然后根据该值过滤列表并返回(新的)过滤列表。

    由于列表通常很大(超过10.000个条目),web应用程序应该在智能手机上运行,并且过滤器考虑了许多值,因此我希望优化计算资源。所以我用 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
    );
    
    0 回复  |  直到 7 年前
        1
  •  4
  •   Bear-Foot    7 年前

    useMemo 而不是 useCallback

    const filteredContacts = useMemo(() => filterContacts(contacts), [
        value
      ]);
    
    ...
    <ContactList contacts={filteredContacts} />
    

    为什么? 使用回调

    您想要的是仅在以下情况下过滤您的联系人: value 变化。 记住函数的最后一个返回值,并且仅当微分参数更改时才会重新运行。它们不会每800毫秒改变一次以上,因为你能很好地消除它的抖动。

    附言:你可以用 阻止 filterContacts 无理由重新计算:

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

    即使在您的情况下,性能增益也是微乎其微的。

        2
  •  3
  •   r g    7 年前

    https://github.com/xnimorz/use-debounce useDebouncedCallback

    const getFilteredContacts = useDebouncedCallback(
        () => filterContactsByValue(value.toLowerCase()),
        800,
        [value]
      );
    

    您也可以使用lodash的debounce或throttle(当您的项目中有lodash时),但正如@skyboyer提到的,您可能会以过期的回调版本结束,并将在适当延迟后运行

    export {debounce} from 'lodash'; 
    
    const getFilteredContacts = useCallback(
        debounce(() => filterContactsByValue(value.toLowerCase()), 1000),
        [value]
    );
    
    

    但是 useMemo

    const FilteredContacts = ({contacts}) => {
        const [filterParam, setFilterParam] = useState('');
        const [value] = useDebounce(filterParam, 800);
        const contactsFilter = useMemo(
            () => filterContactsByValue(value.toLowerCase()),
            [value]
        );
        const filteredContacts = useMemo(
            () => contactsFilter(contacts), 
            [value, contacts]
        );
    
        return (
            <div className="main">
                <SearchBar
                    value={filterParam}
                    onChangeText={setFilterParam}
                />
                <ContactList contacts={filteredContacts} />
            </div>
        );
    }
    
    推荐文章