一、问题背景
import { debounce } from 'lodash'; const [searchKey, setSearchKey] = useState(''); // 防抖函数 const debounceList = debounce(getList, 500);
<Input value={searchKey} onChange={(e) => { setSearchKey(e.target.value); }} className={`${style.search}`} placeholder="请输入关键词" />
页面上有一个搜索框,searchKey是通过useState定义的响应式数据,onChange事件调用了setSearchKey方法,那么只要输入变化时,组件就会重新渲染从而重新生成新的防抖函数debounceList。最终造成防抖功能失效。
二、解决办法
使用 useRef 定义searchKey数据,使其成为非响应式数据,通过 searchKey.current 获取和修改值:
// 搜索关键字 const searchKey = useRef(''); // 修改数据 const setSearchKey = (val) => { searchKey.current = val; };
<Input onChange={(e) => { setSearchKey(e.target.value); }} className={`${style.search}`} placeholder="请输入关键词" />
三、拓展
关于处理防抖失效的问题,可能有人会想到使用 useCallback 来缓存 debounce 防抖函数,比如你可能会这样写:
const [searchKey, setSearchKey] = useState(''); const debounceList = useCallback(debounce(getList, 500), []);
这样防抖功能虽然生效了,但是你无法获取最新的searchKey值;如果想获取最新的searchKey值,就要把searchKey加到后面的 [ ] 中,但是这样防抖又失效了。所以只能采用useRef 定义非响应式数据来解决。