如何使用useCallback使自定义的debounce钩子工作



我确实搜索了这些相关问题,并找到了一些解决方案,但最重要的是关于lodash去抖动。在我的例子中,我将useDebounce创建为自定义挂钩,并直接返回值

我当前的问题是useCallback使用旧的去抖动值

这是我的代码剪辑。

//To makes sure that the code is only triggered once per user input and send the request then.  
export const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => setDebouncedValue(value), delay);
return () => clearTimeout(timeout);
}, [value, delay]);
return debouncedValue;
};

useDebounce按预期工作

export const ShopQuantityCounter = ({ id, qty }) => {
const [value, setValue] = useState(qty);
const debounceInput = useDebounce(value, 300);
const dispatch = useDispatch();
const handleOnInputChange = useCallback((e) => {
setValue(e.target.value);  
console.info('Inside OnChange: debounceInput', debounceInput);

// dispatch(updateCartItem({ id: id, quantity: debounceInput }));
},[debounceInput]);
console.info('Outside OnChange: debounceInput', debounceInput);
// To fixed issue that useState set method not reflecting change immediately
useEffect(() => {
setValue(qty);
}, [qty]);

return (
<div className="core-cart__quantity">

<input
className="core-cart__quantity--total"
type="number"
step="1"
min="1"
title="Qty"
value={value}
pattern="^[0-9]*[1-9][0-9]*$"
onChange={handleOnInputChange}
/>

</div>
);
};
export default ShopQuantityCounter;

以下是console.info的屏幕截图,以解释问题所在。

当前数量
使用onChange 更新

如果您有任何解决方案来修复它,我将不胜感激,也欢迎提出任何需要更新的代码。

这可能有助于实现您想要的目标。您可以创建一个可重复使用的debounce函数,回调如下。

export const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value);
let timeout;
const setDebounce = (newValue) => {
clearTimeout(timeout);
timeout = setTimeout(() => setDebouncedValue(newValue), delay);
};
return [debouncedValue, setDebounce];
};

并像这样在代码中使用该函数。

export const ShopQuantityCounter = ({ id, qty }) => {
const [value, setValue] = useState(qty);
const [debounceInput, setDebounceInput] = useDebounce(value, 300);
const dispatch = useDispatch();
const handleOnInputChange = useCallback((e) => {
setDebounceInput(e.target.value);
console.info('Inside OnChange: debounceInput', debounceInput);

// dispatch(updateCartItem({ id: id, quantity: debounceInput }));
},[debounceInput]);
console.info('Outside OnChange: debounceInput', debounceInput);
// To fixed issue that useState set method not reflecting change immediately
useEffect(() => {
setValue(qty);
}, [qty]);

return (
<div className="core-cart__quantity">

<input
className="core-cart__quantity--total"
type="number"
step="1"
min="1"
title="Qty"
value={value}
pattern="^[0-9]*[1-9][0-9]*$"
onChange={handleOnInputChange}
/>

</div>
);
};
export default ShopQuantityCounter;

最新更新