如何使用RTK查询实现单个查询中的多个api调用

Luc*_*bue 13 reactjs rtk-query

我是 RTK 查询的新手,正在努力解决必须实现的用例。

场景:我必须合并两个 API 调用的结果:第一个 API 调用是私有 API 调用,而第二个 API 调用是公共 API 调用。我需要合并这两个 API 的响应,并将计算结果写入 RTK 缓存,以便 UI 可以相应更新。

问题:我发现一旦调用await queryFullfilled,RTK 查询就会立即将来自该 API 调用的响应写入其缓存,然后当我进行计算并尝试使用缓存更新 RTK 缓存时,缓存apiSlice.util.updateQueryData将再次更改。这意味着 UI 将渲染两次,第一次使用错误的值(人员数组),第二次使用正确的值(由 id 和实体组成的 JSON)。

问题:有没有办法只向 RTK 缓存写入 1 次,这样我就可以得到我需要的计算值?array因为发生的情况是,在某些情况下,我需要JSON才能进入缓存{ids: [...], entities: {}}

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);
        }
      },
    }),
  }),
});
Run Code Online (Sandbox Code Playgroud)

phr*_*hry 12

这是 queryFn 的用例之一:使用单个查询执行多个请求

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 }
      },
    }),
  }),
})
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,我完全错过了文档的那一部分!我会尽快尝试 (2认同)