补丁多个ID和一个请求,带有React查询
我有一个非常基本的应用程序,可以预订座位。用户选择带有<代码>可用的座椅/座椅,点击书籍,补丁请求:false 通过React查询发送到伪造的API(JSON-SERVER),库将请求无效,并立即显示服务器的响应。
数据库结构看起来像这样:
{
"hallA": [
{
"id": 1,
"seat": 1,
"available": false
},
{
"id": 2,
"seat": 2,
"available": true
},
{
"id": 3,
"seat": 3,
"available": false
}
]
}
选择的逻辑,预订座椅看起来像这样:
const App = () => {
const { data, isLoading } = useGetHallLayout("hallA");
const [selected, setSelected] = useState<
{ id: number; seat: number; available: boolean }[]
>([]);
const handleSelect = useCallback(
(seat: { id: number; seat: number; available: boolean }) => {
const itemIdx = selected.findIndex((element) => element.id === seat.id);
if (itemIdx === -1) {
setSelected((prevState) => [
...prevState,
{ id: seat.id, seat: seat.seat, available: !seat.available },
]);
} else {
setSelected((prevState) =>
prevState.filter((element) => element.id !== seat.id)
);
}
},
[selected]
);
const takeSeat = useTakeSeat({
onSuccess: () => {
useGetHallLayout.invalidate();
},
});
const sendRequest = useCallback(() => {
selected.forEach((item) =>
takeSeat.mutateAsync({ id: item.id, hall: "hallA" })
);
setSelected([]);
}, [selected, takeSeat]);
return (
<>
{!isLoading && (
<ConcertHall
layout={data}
onSeatSelect={handleSelect}
activeSeats={selected}
/>
)}
<button disabled={isLoading} onClick={sendRequest}>
Take selected
</button>
</>
);
};
查询看起来像这样:
export const useGetHallLayout = (hall: string) => {
const { data, isLoading } = useQuery(["hall"], () =>
axios.get(`http://localhost:3000/${hall}`).then((res) => res.data)
);
return { data, isLoading };
};
export const useTakeSeat = (options?: UseMutationOptions<unknown, any, any>) =>
useMutation(
(data: { hall: string; id: number }) =>
axios.patch(`http://localhost:3000/${data.hall}/${data.id}`, {
available: false,
}),
{
...options,
}
);
useGetHallLayout.invalidate = () => {
return queryClient.invalidateQueries("hall");
};
上述代码的问题是,我在每个循环中更新每个ID的操作非常昂贵(可用:false:false )并在每次更改后都不会更新一次后查询它无效。
问题是:考虑到JSON服务器的局限性,是否有更好的方法可以做到这一点?任何批处理更新而不是单独向每个ID发送请求?也许逻辑上有一些变化?
提前致谢
I have a very basic prototype of app that allows to book a seat. User selects the seat/seats, clicks book, patch request with available: false
is sent to the fake api (json-server) with React Query, library invalidates the request and immediately shows response from the server.
Database structure looks like this:
{
"hallA": [
{
"id": 1,
"seat": 1,
"available": false
},
{
"id": 2,
"seat": 2,
"available": true
},
{
"id": 3,
"seat": 3,
"available": false
}
]
}
and the logic for selecting, booking seats looks like this:
const App = () => {
const { data, isLoading } = useGetHallLayout("hallA");
const [selected, setSelected] = useState<
{ id: number; seat: number; available: boolean }[]
>([]);
const handleSelect = useCallback(
(seat: { id: number; seat: number; available: boolean }) => {
const itemIdx = selected.findIndex((element) => element.id === seat.id);
if (itemIdx === -1) {
setSelected((prevState) => [
...prevState,
{ id: seat.id, seat: seat.seat, available: !seat.available },
]);
} else {
setSelected((prevState) =>
prevState.filter((element) => element.id !== seat.id)
);
}
},
[selected]
);
const takeSeat = useTakeSeat({
onSuccess: () => {
useGetHallLayout.invalidate();
},
});
const sendRequest = useCallback(() => {
selected.forEach((item) =>
takeSeat.mutateAsync({ id: item.id, hall: "hallA" })
);
setSelected([]);
}, [selected, takeSeat]);
return (
<>
{!isLoading && (
<ConcertHall
layout={data}
onSeatSelect={handleSelect}
activeSeats={selected}
/>
)}
<button disabled={isLoading} onClick={sendRequest}>
Take selected
</button>
</>
);
};
Queries look like this:
export const useGetHallLayout = (hall: string) => {
const { data, isLoading } = useQuery(["hall"], () =>
axios.get(`http://localhost:3000/${hall}`).then((res) => res.data)
);
return { data, isLoading };
};
export const useTakeSeat = (options?: UseMutationOptions<unknown, any, any>) =>
useMutation(
(data: { hall: string; id: number }) =>
axios.patch(`http://localhost:3000/${data.hall}/${data.id}`, {
available: false,
}),
{
...options,
}
);
useGetHallLayout.invalidate = () => {
return queryClient.invalidateQueries("hall");
};
The problem of the above code is that I perform very expensive operation of updating each id in a for each loop (to available: false) and query invalidates it after each change not once all of them are updated.
The question is: is there any better way to do this taking into account the limitations of json-server? Any batch update instead of sending request to each and every id seperately? Maybe some changes in a logic?
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您当然可以进行一个启动多个请求的突变,并以
promise.all
或Promise.allsettled
返回结果。类似的内容:然后,所有查询都将有一个“生命周期”(加载 /错误 /成功),而
OnSuccess < / code>只能调用一次。
我看到的另一个陷阱是,您真的希望
Hall
字符串成为查询密钥的一部分:You can certainly make one mutation that fires of multiple requests, and returns the result with
Promise.all
orPromise.allSettled
. Something like:then, you would have one "lifecycle" (loading / error / success) for all queries together, and
onSuccess
will only be called once.Another gotcha I'm seeing is that you'd really want the
hall
string to be part of the query key: