如何在RTK Query中使用不同baseQuery?我认为应用只能有一个createApi
在RTK Query中使用多种baseQuery的两种方案
你之前的理解有误——RTK Query完全支持创建多个createApi实例,也可以在同一个实例里动态切换不同的baseQuery。下面给你两种可行的实现方式:
方案一:创建多个独立的API切片
如果你的REST API和GraphQL API是完全独立的业务模块,直接分开创建两个createApi实例是最简单的方案,各自使用对应的baseQuery,最后都注册到Redux Store即可。
步骤1:分别定义两个API切片
保留你原来的两个代码示例,作为独立的切片:
// restApiSlice.js export const restApiSlice = createApi({ reducerPath: "restApiSlice", baseQuery: axiosBaseQuery, endpoints: (builder) => ({ fetchSomething: builder.query<Resource, string>({ query: (resourceUUID) => ({ url: `/services/buresource/collections/${resourceUUID}?component_level=1`, method: "get", }), }), }), }); // graphqlApiSlice.js export const graphqlApiSlice = createApi({ reducerPath: "graphqlApiSlice", baseQuery: graphqlBaseQuery({ baseUrl: 'https://graphqlzero.almansi.me/api', }), endpoints: (builder) => ({ getPosts: builder.query({ query: () => ({ body: gql` query { posts { data { id title } } } `, }), transformResponse: (response) => response.posts.data, }), }), })
步骤2:注册到Redux Store
在配置Store时,把两个切片的reducer和middleware都加进去:
import { configureStore } from '@reduxjs/toolkit'; import { restApiSlice } from './restApiSlice'; import { graphqlApiSlice } from './graphqlApiSlice'; export const store = configureStore({ reducer: { [restApiSlice.reducerPath]: restApiSlice.reducer, [graphqlApiSlice.reducerPath]: graphqlApiSlice.reducer, }, middleware: (getDefaultMiddleware) => getDefaultMiddleware() .concat(restApiSlice.middleware) .concat(graphqlApiSlice.middleware), });
使用方式
在组件里分别导入两个切片生成的hooks即可:
import { useFetchSomethingQuery } from './restApiSlice'; import { useGetPostsQuery } from './graphqlApiSlice'; function MyComponent() { const { data: restData } = useFetchSomethingQuery('some-uuid'); const { data: graphqlData } = useGetPostsQuery(); // 渲染数据... }
方案二:在同一个API切片中动态切换baseQuery
如果希望把所有接口放在同一个切片里,可以自定义一个复合baseQuery,根据每个endpoint的配置来选择使用axios还是graphql的baseQuery。
实现复合baseQuery
import { createApi, BaseQueryFn } from '@reduxjs/toolkit/query/react'; import axiosBaseQuery from './axiosBaseQuery'; import graphqlBaseQuery from './graphqlBaseQuery'; // 定义自定义查询参数类型,标记使用哪种baseQuery type CustomQueryArgs = | { type: 'rest'; url: string; method: string; [key: string]: any } | { type: 'graphql'; body: any; [key: string]: any }; const customBaseQuery: BaseQueryFn<CustomQueryArgs, unknown, unknown> = async (args, api, extraOptions) => { if (args.type === 'rest') { // 调用axios的baseQuery,移除type标记 const { type, ...restArgs } = args; return axiosBaseQuery(restArgs, api, extraOptions); } else if (args.type === 'graphql') { // 调用graphql的baseQuery,移除type标记 const { type, ...restArgs } = args; return graphqlBaseQuery({ baseUrl: 'https://graphqlzero.almansi.me/api' })(restArgs, api, extraOptions); } throw new Error('Unknown query type'); };
创建统一的API切片
export const unifiedApiSlice = createApi({ reducerPath: "unifiedApiSlice", baseQuery: customBaseQuery, endpoints: (builder) => ({ // REST接口,标记type为rest fetchSomething: builder.query<Resource, string>({ query: (resourceUUID) => ({ type: 'rest', url: `/services/buresource/collections/${resourceUUID}?component_level=1`, method: "get", }), }), // GraphQL接口,标记type为graphql getPosts: builder.query({ query: () => ({ type: 'graphql', body: gql` query { posts { data { id title } } } `, }), transformResponse: (response) => response.posts.data, }), }), });
使用方式
直接导入统一切片的hooks即可:
import { useFetchSomethingQuery, useGetPostsQuery } from './unifiedApiSlice'; function MyComponent() { const { data: restData } = useFetchSomethingQuery('some-uuid'); const { data: graphqlData } = useGetPostsQuery(); // 渲染数据... }
两种方案的选择建议
- 如果两个API的业务逻辑完全独立,**方案一(多个切片)**更清晰,维护成本更低。
- 如果需要在不同接口之间共享缓存状态或依赖关系,**方案二(统一切片)**更合适。
内容的提问来源于stack exchange,提问作者Zim
相关产品推荐
相关产品推荐

