如何使自定义防抖钩子与 useCallback 一起使用?

问题描述 投票:0回答:1

我确实搜索了这些相关问题并找到了一些解决方案,但大多数是关于 lodash debounce 的。就我而言,我创建

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
的屏幕截图来解释问题所在。

Current quantity
Updated with onChange

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

reactjs react-hooks debouncing
1个回答
0
投票

这可能会帮助您实现您想要的目标。您可以使用如下回调创建可重用的去抖函数。

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;
© www.soinside.com 2019 - 2024. All rights reserved.