如何在React Hook中正确设置防抖?当前实现每输入字符就触发请求
问题根因
你的防抖失效核心是防抖函数实例频繁重建,具体原因是useCallback的依赖数组包含了不必要的dataEnrichedCompanies:
- 每次请求返回后
dataEnrichedCompanies都会更新,触发useCallback重新执行,生成全新的防抖函数实例 - 每个防抖实例都有独立的计时上下文,之前输入触发的计时直接失效,每输入一个字符都会触发新的计时,到点后全部依次执行,就出现了频繁发请求的问题
修复方案
优先用useRef持久化防抖实例,保证组件生命周期内只有一个防抖函数,不会因为依赖变化重建:
const [inputValue, setInputValue] = useState(''); // 用useRef存储防抖函数,实例永不重建 const debounceFetchCompanies = useRef( debounce((value: string) => { if (value.trim().length >= 3) { refetchEnrichedCompanies({ name: value.trim(), }); } }, 500) ).current; // 组件卸载时清理未执行的防抖定时器 useEffect(() => { return () => { // 若你使用的防抖工具提供cancel方法就调用,没有的话可自行存储定时器id做清理 debounceFetchCompanies.cancel?.(); }; }, [debounceFetchCompanies]); const handleChange = useCallback((value: string) => { setInputValue(value); debounceFetchCompanies(value); }, [debounceFetchCompanies]);
额外注意项
- 确认
refetchEnrichedCompanies引用稳定:如果是来自React Query/SWR等数据请求库,返回的refetch方法默认引用稳定,无需额外处理;如果是自定义的请求方法,需要用useCallback包裹避免引用频繁变化 - 若
inputValue仅用于请求参数,无需做其他渲染逻辑,可以不用存入useState,直接传递给防抖函数即可,减少不必要的组件重渲染
内容的提问来源于stack exchange,提问作者Pierre Olivier Tran
相关产品推荐
相关产品推荐

