kishorekumaru
kishorekumaru

Reputation: 1578

How to intercept multiple Redux toolkit Createapi

I am using this solution https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#automatic-re-authorization-by-extending-fetchbasequery to write reAuth baseQuery.

However I have multiple backend services with different createAPI services consume same refresh token concept.

Is there any way to have one baseQueryAuth can be used for multiple createApis

for example

productQuery.tsx

const baseQueryWithReauth: BaseQueryFn<
  string | FetchArgs,
  unknown,
  FetchBaseQueryError
> = async (args, api, extraOptions) => {
  let result = await baseQuery(args, api, extraOptions)
  if (result.error && result.error.status === 401) {
     // reset token
  }
  return result
}
/** Product Query **/
const baseQuery = fetchBaseQuery({
  baseUrl: process.env.REACT_APP_PRODUCT_URL,
  prepareHeaders: (headers) => {
    headers.set('Authorization', `Bearer ${token}`);
    return headers;
  },
});

const productAPI = createApi({
   reducerPath: 'productAPI',
  baseQuery: baseQueryWithReauth,
  endpoints: (builder) => {
    ...
    ...
    }
   })

On customerQuery.tsx

const baseQueryWithReauth: BaseQueryFn<
  string | FetchArgs,
  unknown,
  FetchBaseQueryError
> = async (args, api, extraOptions) => {
  let result = await baseQuery(args, api, extraOptions)
  if (result.error && result.error.status === 401) {
     // reset token
  }
  return result
}
/** Customer Query **/
const baseQuery = fetchBaseQuery({
  baseUrl: process.env.REACT_APP_CUSTOMER_URL,
  prepareHeaders: (headers) => {
    headers.set('Authorization', `Bearer ${token}`);
    return headers;
  },
});

const customerAPI = createApi({
   reducerPath: 'customerAPI',
  baseQuery: baseQueryWithReauth,
  endpoints: (builder) => {
    ...
    ...
    }
   })

Is there any way I can move the baseQueryWithReauth outside as one function and pass/bind the baseQuery based on different API?

Upvotes: 5

Views: 2827

Answers (1)

diedu
diedu

Reputation: 20815

Yes, you can create a higher order function with currying, baseQueryWithReauth will be a function that receives a baseQuery function as an argument and returns another baseQuery function

import { fetchBaseQuery } from "@reduxjs/toolkit/query";
import { createApi } from '@reduxjs/toolkit/query'
...

type BaseQueryType = ReturnType<typeof fetchBaseQuery>;

const baseQueryWithReauth: (baseQuery: BaseQueryType) => BaseQueryType = (
  baseQuery
) => async (args, api, extraOptions) => {
  let result = await baseQuery(args, api, extraOptions)
  if (result.error && result.error.status === 401) {
     // reset token
  }
  return result
}

and then use it to build each API

const productBaseQuery = fetchBaseQuery({
  baseUrl: process.env.REACT_APP_PRODUCT_URL,
  prepareHeaders: (headers) => {
    headers.set('Authorization', `Bearer ${token}`);
    return headers;
  },
});

const productAPI = createApi({
  reducerPath: "customerAPI",
  baseQuery: baseQueryWithReauth(productBaseQuery),
  endpoints: (builder) => {
    ...
  },
});
const customerBaseQuery = fetchBaseQuery({
  baseUrl: process.env.REACT_APP_CUSTOMER_URL,
  prepareHeaders: (headers) => {
    headers.set("Authorization", `Bearer ${token}`);
    return headers;
  },
});

const customerAPI = createApi({
  reducerPath: "customerAPI",
  baseQuery: baseQueryWithReauth(customerBaseQuery),
  endpoints: (builder) => {
    ...
  },
});

here is a sandbox for reference

https://codesandbox.io/s/hof-redux-toolkit-api-dlel1g?file=/src/api.ts

Upvotes: 9

Related Questions