useCallback 的依赖数组不起作用

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

我有一个useCallback函数和一个snackbar状态,每次调用deleteRow函数时,snackbar状态都会更新,但是setSnackbar函数不会更新我们传递的第一个值,所以当我们从snackbar登录时,snackbar没有所有值我们传递给它

const deleteRow = useCallback(async (item: ICheckoutItem, ppid: number, isLastOne = false) => {
        let newItems = [...checkoutItems];
        newItems = newItems.map(((item) => {
            item.properties = item.properties.filter((property) => property.id !== ppid);
            return item;
        }));

        newItems = newItems.filter((item) => item.properties.length > 0);

        setCheckoutItems(newItems);

        await server_axios.delete(endpoints.orderProductProperties.delete(ppid) + (orderId ? `?order_id=${orderId}` : ''));

        await new Promise((resolve) => setTimeout(resolve, 500));

        if (isLastOne && type === 'edit') {
            enqueueSnackbar(
                `تمامی کالاهای پروفیل ${item.product.name} با موفقیت حذف شدند.\nهمچنین وضعیت سفارش شما به «حذف‌شده» تغییر داده شد.`,
                {
                    variant: 'multiline',
                    color: 'info',
                }
            );
            console.log(snackbar)
            snackbar.forEach((id) => {
                closeSnackbar(id)
            })
            setSnackbar([])
        } else if (!isLastOne) {
            const esId: SnackbarKey = enqueueSnackbar('کالای مورد نظر با موفقیت حذف شد.', {
                color: 'info',
                variant: 'myCustomVariant',
                showTimer: true,
                showButton: true,
                autoHideDuration: 10 * 1000,
                onClick: async () => {
                    await server_axios.patch(endpoints.orderProductProperties.cancel_delete(ppid))
                    if (onRefresh) onRefresh();
                }
            })
            setSnackbar(currentSnackbar => {
                console.log('Previous snackbar state:', currentSnackbar);
                console.log('New snackbar ID:', esId);
                const newState = [...currentSnackbar, esId];
                console.log('New snackbar state:', newState);
                return newState;
            });
            // updateSnack(esId)
            // console.log(esId)
            // let newSnackbar = snackbar.length ? [...snackbar, esId] : [esId]
            // console.log(newSnackbar)
            // setSnackbar([...newSnackbar])
        }

        if (afterUpdate) afterUpdate((newItems.length === 0));

    }, [checkoutItems, orderId, type, snackbar]);
javascript reactjs next.js
1个回答
0
投票

这里的问题是,由于 React 在闭包中处理状态的方式,当

snackbar
运行时,
deleteRow
可能没有最新状态。

要解决此问题,请尝试使用

setSnackbar
进行功能更新,这可确保您始终拥有最新的小吃栏状态:

setSnackbar((currentSnackbar) => {
    currentSnackbar.forEach((id) => closeSnackbar(id));
    return [];
});

此外,从

snackbar
中的依赖项数组中删除
useCallback
,因为使用功能更新程序意味着您不需要它作为依赖项。这应该会阻止页面重置并使您的注意力保持在应有的位置。

这是完整的示例:

const deleteRow = useCallback(async (item: ICheckoutItem, ppid: number, isLastOne = false) => {
    let newItems = [...checkoutItems];
    newItems = newItems.map((item) => {
        item.properties = item.properties.filter((property) => property.id !== ppid);
        return item;
    });

    newItems = newItems.filter((item) => item.properties.length > 0);
    setCheckoutItems(newItems);

    await server_axios.delete(endpoints.orderProductProperties.delete(ppid) + (orderId ? `?order_id=${orderId}` : ''));
    await new Promise((resolve) => setTimeout(resolve, 500));

    if (isLastOne && type === 'edit') {
        enqueueSnackbar(
            `تمامی کالاهای پروفیل ${item.product.name} با موفقیت حذف شدند.\nهمچنین وضعیت سفارش شما به «حذف‌شده» تغییر داده شد.`,
            {
                variant: 'multiline',
                color: 'info',
            }
        );
        
        // Close all snackbars based on the latest state of `snackbar`
        setSnackbar((currentSnackbar) => {
            currentSnackbar.forEach((id) => closeSnackbar(id));
            return [];
        });

    } else if (!isLastOne) {
        const esId: SnackbarKey = enqueueSnackbar('کالای مورد نظر با موفقیت حذف شد.', {
            color: 'info',
            variant: 'myCustomVariant',
            showTimer: true,
            showButton: true,
            autoHideDuration: 10 * 1000,
            onClick: async () => {
                await server_axios.patch(endpoints.orderProductProperties.cancel_delete(ppid));
                if (onRefresh) onRefresh();
            }
        });

        setSnackbar((currentSnackbar) => {
            const newState = [...currentSnackbar, esId];
            console.log('New snackbar state:', newState);
            return newState;
        });
    }

    if (afterUpdate) afterUpdate(newItems.length === 0);

}, [checkoutItems, orderId, type, afterUpdate, onRefresh]);
© www.soinside.com 2019 - 2024. All rights reserved.