如何使用 RTK 查询在单个查询中实现多个 api 调用
How to implement multiple api call in a single query with RTK query
我是 RTK 查询的新手,我正在努力解决我必须实施的用例。
场景:
我必须合并两个 API 调用的结果:第一个 API 调用是私人 API 调用,而第二个是 public API 调用。我需要合并这两个 API 的响应并将计算结果写入 RTK 缓存,以便 UI 可以相应地更新。
问题:
我看到一旦 await queryFullfilled
被调用,RTK 查询立即将 API 调用的响应写入其缓存,然后当我进行计算并尝试使用 [= 更新 RTK 缓存时13=] 缓存会再次改变。这意味着 UI 将渲染两次,第一次使用错误的值(一组人),第二次使用正确的值(由 id 和实体组成的 JSON)。
问题:
有没有办法只将 1 次写入 RTK 缓存,这样我就可以得到我需要的计算值?因为发生的事情是,在某些情况下,当我需要 {ids: [...], entities: {}}
JSON.
时,我进入了缓存 array
import { createEntityAdapter } from '@reduxjs/toolkit';
import axios from 'axios';
export const personsAdapter = createEntityAdapter();
const permitsInitialState = personsAdapter.getInitialState();
export const apiSlice = myServiceApi.injectEndpoints({
endpoints: (builder) => ({
getPersons: builder.query({
query: () => ({ url: '/persons', method: 'get' }),
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
try {
// Resolving the private API call
const { data: persons } = await queryFulfilled;
// Just a random public API call
const { data: todos } = await axios('https://jsonplaceholder.typicode.com/todos');
const enhancedPersons = /** Here the logic that merge the todos and the persons */
const state = personsAdapter.setAll(permitsInitialState, enhancedPermits);
dispatch(
apiSlice.util.updateQueryData('getPersons', _, (draft) => {
Object.assign(draft, state);
})
);
} catch (e) {
console.error(e);
}
},
}),
}),
});
这是queryFn: Performing multiple requests with a single query
的用例之一
import {
createApi,
fetchBaseQuery,
FetchBaseQueryError,
} from '@reduxjs/toolkit/query'
import { Post, User } from './types'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/ ' }),
endpoints: (build) => ({
getRandomUserPosts: build.query<Post, void>({
async queryFn(_arg, _queryApi, _extraOptions, fetchWithBQ) {
// get a random user
const randomResult = await fetchWithBQ('users/random')
if (randomResult.error) throw randomResult.error
const user = randomResult.data as User
const result = await fetchWithBQ(`user/${user.id}/posts`)
return result.data
? { data: result.data as Post }
: { error: result.error as FetchBaseQueryError }
},
}),
}),
})
我是 RTK 查询的新手,我正在努力解决我必须实施的用例。
场景: 我必须合并两个 API 调用的结果:第一个 API 调用是私人 API 调用,而第二个是 public API 调用。我需要合并这两个 API 的响应并将计算结果写入 RTK 缓存,以便 UI 可以相应地更新。
问题:
我看到一旦 await queryFullfilled
被调用,RTK 查询立即将 API 调用的响应写入其缓存,然后当我进行计算并尝试使用 [= 更新 RTK 缓存时13=] 缓存会再次改变。这意味着 UI 将渲染两次,第一次使用错误的值(一组人),第二次使用正确的值(由 id 和实体组成的 JSON)。
问题:
有没有办法只将 1 次写入 RTK 缓存,这样我就可以得到我需要的计算值?因为发生的事情是,在某些情况下,当我需要 {ids: [...], entities: {}}
JSON.
array
import { createEntityAdapter } from '@reduxjs/toolkit';
import axios from 'axios';
export const personsAdapter = createEntityAdapter();
const permitsInitialState = personsAdapter.getInitialState();
export const apiSlice = myServiceApi.injectEndpoints({
endpoints: (builder) => ({
getPersons: builder.query({
query: () => ({ url: '/persons', method: 'get' }),
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
try {
// Resolving the private API call
const { data: persons } = await queryFulfilled;
// Just a random public API call
const { data: todos } = await axios('https://jsonplaceholder.typicode.com/todos');
const enhancedPersons = /** Here the logic that merge the todos and the persons */
const state = personsAdapter.setAll(permitsInitialState, enhancedPermits);
dispatch(
apiSlice.util.updateQueryData('getPersons', _, (draft) => {
Object.assign(draft, state);
})
);
} catch (e) {
console.error(e);
}
},
}),
}),
});
这是queryFn: Performing multiple requests with a single query
的用例之一import {
createApi,
fetchBaseQuery,
FetchBaseQueryError,
} from '@reduxjs/toolkit/query'
import { Post, User } from './types'
const api = createApi({
baseQuery: fetchBaseQuery({ baseUrl: '/ ' }),
endpoints: (build) => ({
getRandomUserPosts: build.query<Post, void>({
async queryFn(_arg, _queryApi, _extraOptions, fetchWithBQ) {
// get a random user
const randomResult = await fetchWithBQ('users/random')
if (randomResult.error) throw randomResult.error
const user = randomResult.data as User
const result = await fetchWithBQ(`user/${user.id}/posts`)
return result.data
? { data: result.data as Post }
: { error: result.error as FetchBaseQueryError }
},
}),
}),
})