J. *_*ers 5 reactjs react-component react-hooks
我有一个名为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>
);
}
Run Code Online (Sandbox Code Playgroud)
我想知道这是否可以,或者返回这样的值是否是不好的做法。如果它很糟糕,为什么以及如何改进它?
编辑:
该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
);
Run Code Online (Sandbox Code Playgroud)
简短的回答:使用useMemo代替useCallback,如下所示:
const filteredContacts = useMemo(() => filterContacts(contacts), [
value
]);
...
<ContactList contacts={filteredContacts} />
Run Code Online (Sandbox Code Playgroud)
为什么?useCallback记住函数的创建。这意味着,如果比较参数相同,则函数的引用将相同。不过,它仍然会每次被调用,并且在您的情况下,不会阻止任何计算。
您想要的是仅在value发生变化时过滤您的联系人。useMemo记住函数的最后一个返回值,并且仅在比较参数更改时才会重新运行。而且它们每 800 毫秒不会改变一次以上,因为你可以很好地消除它。
PS:您可以用来useCallback防止filterContacts无缘无故地重新计算,如下所示:
const filterContacts = useCallback(() => filterContactsByValue(value.toLowerCase()), [value]);
Run Code Online (Sandbox Code Playgroud)
即使在你的情况下,性能增益也是很小的。
根据https://github.com/xnimorz/use-debounce你已经有useDebouncedCallback钩子了。
const getFilteredContacts = useDebouncedCallback(
() => filterContactsByValue(value.toLowerCase()),
800,
[value]
);
Run Code Online (Sandbox Code Playgroud)
您还可以使用 lodash 的去抖或节流(当您的项目中有 lodash 时),但正如 @skyboyer 提到的,您可能会以过时的回调版本结束,将在适当的延迟后运行
export {debounce} from 'lodash';
const getFilteredContacts = useCallback(
debounce(() => filterContactsByValue(value.toLowerCase()), 1000),
[value]
);
Run Code Online (Sandbox Code Playgroud)
但这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>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5173 次 |
| 最近记录: |