【发布时间】:2023-02-03 08:25:51
【问题描述】:
我已经处理了一段时间这个问题,但仍然无法解决。
我正在使用 React-query 作为服务器状态管理库,并且我试图在发生突变时使我的 UI 状态与我的服务器状态同步。因为我可以使用突变响应来避免新的 API 调用,所以我使用了 React-query 为我们提供的 setQueryData 功能。
问题是当突变成功时旧数据被正确修改(我可以在 react-query DevTools 中看到它),但是使用它的组件没有被重新渲染,使我的 UI 状态不同步我的服务器状态(好吧,至少用户看不到更新)。
让我展示一些代码,希望有人能给我一些见解。
Component using the query:
const Detail = ({ orderId }) => {
const { workGroups } = useWorkGroups();
const navigate = useNavigate();
const queryClient = useQueryClient();
const orderQueries = queryClient.getQueryData(["orders"]);
const queryOrder = orderQueries?.find((ord) => ord.id === orderId);
// more code
Component mutating the query:
const Deliver = ({
setIsModalOpened,
artisan,
index,
queryQuantity,
queryOrder,
}) => {
const [quantity, setQuantity] = useState(() => queryQuantity);
const { mutate: confirmOrderDelivered } = useMutateOrderDeliveredByArtisan(
queryOrder.id
);
const onSubmit = () => {
confirmOrderDelivered(
{
id: queryOrder.artisan_production_orders[index].id,
artisan: artisan.user,
items: [
{
quantity_delivered: quantity,
},
],
},
{
onSuccess: setIsModalOpened(false),
}
);
};
// more code
Now the mutation function (ik it's a lot of logic but I dont' want to refetch the data using invalidateQueries since we're dealing with users with a really bad internet connection). Ofc you don't need to understand each step of the fn but what it basically does is update the old queried data. In the beginning I thought it was a mutation reference problem since React using a strict comparison under the hood but I also checked it and It doesn't look like it's the problem. :
{
onSuccess: (data) => {
queryClient.setQueryData(["orders"], (oldQueryData) => {
let oldQueryDataCopy = [...oldQueryData];
const index = oldQueryDataCopy.findIndex(
(oldData) => oldData.id === orderId
);
let artisanProdOrders =
oldQueryDataCopy[index].artisan_production_orders;
let artisanProductionOrderIdx = artisanProdOrders.findIndex(
(artProdOrd) => artProdOrd.id === data.id
);
artisanProdOrders[artisanProductionOrderIdx] = {
...artisanProdOrders[artisanProductionOrderIdx],
items: data.items,
};
const totalDelivered = artisanProdOrders.reduce((acc, el) => {
const delivered = el.items[0].quantity_delivered;
return acc + delivered;
}, 0);
oldQueryDataCopy[index] = {
...oldQueryDataCopy[index],
artisan_production_orders: artisanProdOrders,
items: [
{
...oldQueryDataCopy[index].items[0],
quantity_delivered: totalDelivered,
},
],
};
return oldQueryDataCopy;
});
},
onError: (err) => {
throw new Error(err);
},
}
最后但并非最不重要的一点是:我已经检查过 oldQueryData 是否被正确修改(控制台登录到突变响应中的 onSuccess fn),并且正如我之前所说,数据在 React-query DevTools 中被正确修改。
我知道这是很多代码,问题似乎很复杂,但我真的相信这可能是一件非常简单的事情,我没有指出,因为我已经很累了。
谢谢!
【问题讨论】:
标签: javascript reactjs react-query