在使用 RTK 查询时,第一个请求不会发送到数据库
the first request doesn't send to the database in working with RTK query
在我的项目中,我想增加和减少所列食物的数量。但在第一个请求中按下“更多”按钮后,数据库中的任何内容都不会改变,但在第二个请求中再次按下后,只需增加一次(刷新页面后你就会明白)。其实我不知道为什么第一个请求不算数。
演示:https://laughing-jang-201dc1.netlify.app/ .
Github : https://github.com/alibidjandy/burger
这是主要的 RTK 查询配置:
https://github.com/alibidjandy/burger/blob/main/src/Api/apiSlice.ts
import { current } from "@reduxjs/toolkit";
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import {
AllBurgerType,
BurgerType,
IngredientsType,
} from "../components/Layouts/burger/burgerSlice/burgerSlice";
export const burgerApi = createApi({
reducerPath: "burgerApi",
tagTypes: ["Ingredients"],
baseQuery: fetchBaseQuery({
baseUrl:
"https://burger-order-brown-default-rtdb.europe-west1.firebasedatabase.app",
}),
endpoints: (builder) => ({
getIngredients: builder.query<BurgerType, undefined>({
// query: () => `/.json`,
query: () => {
return { url: "/.json", method: "GET" };
},
providesTags: ["Ingredients"],
}),
editIngredients: builder.mutation({
query: (initialIngredients) => {
return { url: "/.json", method: "PATCH", body: initialIngredients };
},
invalidatesTags: ["Ingredients"],
}),
increase: builder.mutation({
query: ({ ing }) => {
return {
url: `/ingredients/${ing.id}/.json`,
method: "PATCH",
body: ing,
};
},
async onQueryStarted({ ing }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
burgerApi.util.updateQueryData(
"getIngredients",
undefined,
(draft) => {
console.log("increase");
// debugger;
const ingredient = draft.ingredients.find(
(ingredient) => ingredient.title === ing.title
);
if (ingredient) {
console.log(current(ingredient));
ingredient.Qty!++;
}
}
)
);
try {
await queryFulfilled;
} catch {
console.log("crashed");
patchResult.undo();
}
},
}),
decrease: builder.mutation({
query: ({ ing, indexIng }) => {
return {
url: `/ingredients/${indexIng}/.json`,
method: "POST",
body: ing,
};
},
async onQueryStarted({ ing, indexIng }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
burgerApi.util.updateQueryData(
"getIngredients",
undefined,
(draft) => {
console.log("decrese");
const ingredient = draft.ingredients[indexIng];
if (ingredient.Qty !== undefined && ingredient.Qty > 0) {
draft.totalCost = +(draft.totalCost -=
ingredient.cost!).toFixed(2);
ingredient.Qty--;
}
}
)
);
try {
await queryFulfilled;
} catch {
patchResult.undo();
}
},
}),
}),
});
export const { editIngredients, getIngredients } = burgerApi.endpoints;
export const {
useGetIngredientsQuery,
useEditIngredientsMutation,
useIncreaseMutation,
useDecreaseMutation,
} = burgerApi;
等等...我正在重读您的代码。我认为您可能对 onQueryStarted
和 updateQueryData
的作用有非常错误的想法。 onQueryStarted
在 您的请求发送到服务器后 运行。 updateQueryData
仅在客户端更新您的数据。
因此,您将旧的客户端数据发送到服务器,然后在客户端更新它。
是的,难怪你的数据总是落后一步。
您需要首先将更新的数据发送到服务器。
你需要做类似
的事情
increase: builder.mutation({
query: ({ ing }) => {
return {
url: `/ingredients/${ing.id}/.json`,
method: "PATCH",
body: { ...ing, Qty: ing.Qty + 1 }
};
},
而且根本没有 onQueryStarted
。
之后只需使用 invalidatesTags
从服务器重新获取正确的数据。
此外,正如我在您代码的其他地方偶然发现的那样:您正在使用 nanoid()
生成 id
并将其用作 key
。永远不要那样做。 key
必须是稳定的,不能在每次渲染时都不同。这总是会导致 React 在每次渲染时销毁整个子组件 DOM 并丢弃所有子组件的整个本地状态。
在我的项目中,我想增加和减少所列食物的数量。但在第一个请求中按下“更多”按钮后,数据库中的任何内容都不会改变,但在第二个请求中再次按下后,只需增加一次(刷新页面后你就会明白)。其实我不知道为什么第一个请求不算数。
演示:https://laughing-jang-201dc1.netlify.app/ .
Github : https://github.com/alibidjandy/burger
这是主要的 RTK 查询配置:
https://github.com/alibidjandy/burger/blob/main/src/Api/apiSlice.ts
import { current } from "@reduxjs/toolkit";
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import {
AllBurgerType,
BurgerType,
IngredientsType,
} from "../components/Layouts/burger/burgerSlice/burgerSlice";
export const burgerApi = createApi({
reducerPath: "burgerApi",
tagTypes: ["Ingredients"],
baseQuery: fetchBaseQuery({
baseUrl:
"https://burger-order-brown-default-rtdb.europe-west1.firebasedatabase.app",
}),
endpoints: (builder) => ({
getIngredients: builder.query<BurgerType, undefined>({
// query: () => `/.json`,
query: () => {
return { url: "/.json", method: "GET" };
},
providesTags: ["Ingredients"],
}),
editIngredients: builder.mutation({
query: (initialIngredients) => {
return { url: "/.json", method: "PATCH", body: initialIngredients };
},
invalidatesTags: ["Ingredients"],
}),
increase: builder.mutation({
query: ({ ing }) => {
return {
url: `/ingredients/${ing.id}/.json`,
method: "PATCH",
body: ing,
};
},
async onQueryStarted({ ing }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
burgerApi.util.updateQueryData(
"getIngredients",
undefined,
(draft) => {
console.log("increase");
// debugger;
const ingredient = draft.ingredients.find(
(ingredient) => ingredient.title === ing.title
);
if (ingredient) {
console.log(current(ingredient));
ingredient.Qty!++;
}
}
)
);
try {
await queryFulfilled;
} catch {
console.log("crashed");
patchResult.undo();
}
},
}),
decrease: builder.mutation({
query: ({ ing, indexIng }) => {
return {
url: `/ingredients/${indexIng}/.json`,
method: "POST",
body: ing,
};
},
async onQueryStarted({ ing, indexIng }, { dispatch, queryFulfilled }) {
const patchResult = dispatch(
burgerApi.util.updateQueryData(
"getIngredients",
undefined,
(draft) => {
console.log("decrese");
const ingredient = draft.ingredients[indexIng];
if (ingredient.Qty !== undefined && ingredient.Qty > 0) {
draft.totalCost = +(draft.totalCost -=
ingredient.cost!).toFixed(2);
ingredient.Qty--;
}
}
)
);
try {
await queryFulfilled;
} catch {
patchResult.undo();
}
},
}),
}),
});
export const { editIngredients, getIngredients } = burgerApi.endpoints;
export const {
useGetIngredientsQuery,
useEditIngredientsMutation,
useIncreaseMutation,
useDecreaseMutation,
} = burgerApi;
等等...我正在重读您的代码。我认为您可能对 onQueryStarted
和 updateQueryData
的作用有非常错误的想法。 onQueryStarted
在 您的请求发送到服务器后 运行。 updateQueryData
仅在客户端更新您的数据。
因此,您将旧的客户端数据发送到服务器,然后在客户端更新它。
是的,难怪你的数据总是落后一步。
您需要首先将更新的数据发送到服务器。
你需要做类似
的事情 increase: builder.mutation({
query: ({ ing }) => {
return {
url: `/ingredients/${ing.id}/.json`,
method: "PATCH",
body: { ...ing, Qty: ing.Qty + 1 }
};
},
而且根本没有 onQueryStarted
。
之后只需使用 invalidatesTags
从服务器重新获取正确的数据。
此外,正如我在您代码的其他地方偶然发现的那样:您正在使用 nanoid()
生成 id
并将其用作 key
。永远不要那样做。 key
必须是稳定的,不能在每次渲染时都不同。这总是会导致 React 在每次渲染时销毁整个子组件 DOM 并丢弃所有子组件的整个本地状态。