我有一个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]);
这里的问题是,由于 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]);