我有一个相对简单的React钩子来反跳一个值。唯一的不足是,我想提供一个在去抖动值更改时触发的回调。我知道我可以在App
内有另一个useEffect来监听debouncedValue
上的更改,但我想将此行为集成到可重用的挂钩中。
const useDebounce = (value, delay, { onChange }) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(value);
onChange(value);
}, delay);
return () => {
clearTimeout(timeout);
};
}, [value, delay, onChange]);
return debouncedValue;
};
const App = () => {
const [value, setValue] = useState("");
const debouncedValue = useDebounce(value, 750, { onChange: (value) => console.log(value) });
return (
<div style={{ margin: 50 }}>
<input value={value} onChange={(event) => setValue(event.target.value)} />
<p>{value}</p>
<p>{debouncedValue}</p>
</div>
);
};
现在,我遇到的问题是onChange
每次去抖动都会触发两次。显然,onChange
回调必须是useEffect
的依赖项数组的一部分,即使我不在乎它何时更新也是如此。但这产生了问题,而不是在每个渲染器上都为{ onChange: (value) => console.log(value) }
创建一个新对象,因此引用相等性认为useEffect
的依赖关系已更改。我可以在组件之外创建对象,但这也会使钩子的API复杂化。
所以,我的问题是:解决此问题的最简单方法是什么?理想情况下,无需拉入任何第三方包装。我可以想到的解决方法是编写一个自定义的useEffect挂钩,该挂钩可以进行深层比较,但我希望有人可以为我提供一个更简单的解决方案。