Skip to content

Re-use Api Endpoints & Extend RTK Query Base Queries #3674

Open
@miordache93

Description

@miordache93

Scenario

I have a monorepo setup made with nx which contains 2 web apps and a set of libs. Libs are splitted as shared-lib and admin-lib. Each lib has it's own redux setup (store, slices and rtkq apis). Given that for my admin app I've created a dedicated admin-lib, there is an rtkq api which I want to extend from the shared-lib.

All good so far, i can use mySharedApi.injectEndpoints({...}) and it works.

Problem

Both APIs have their own custom implementation of baseQuery, on admin one I also have a handler for when an api endpoint gives 403 and dispatches an action inside it's custom baseQuery implementation to notify the app the user isn't allowed to access certain resources. But since I need some endpoints only from the sharedApi, that api isn't linked to second baseQuery, therefore the admin one isn't called.

Summary

How can i merge 2 API endpoints and override the baseQuery from the one that's extended.

Some code for reference:

export const adminApi = sharedApi.injectEndpoints({
  _reducerPath: 'adminApi',_
  _baseQuery: baseAdminQueryWithReauth({ baseUrl: 'resource', retries: 3 }),_ << custom baseQuery with 403 handler
  _tagTypes: ['Resources'],_
  endpoints: builder => ({      
    getAdminResources: builder
        .query<any, Partial<any>>({
          query: query => '/v2/search?${ stringify(query) }',
          providesTags: ['Resources'],
        }),
   });  
  export const sharedApi = createApi({
  reducerPath: 'sharedApi',
  baseQuery: baseQueryWithReauth({ baseUrl: 'resource', retries: 3 }), << custom baseQuery **without** 403 handler
  tagTypes: ['Resources'],
  endpoints: builder => ({      
    someNonAdminEndpoint: builder
        .query<any, Partial<any>>({
          query: query => '/v2/search?${ stringify(query) }',
          providesTags: ['Resources'],
        }),
   }); 
  export const createBaseQuery = ({ baseUrl = '', retries = 0 }) => {
  const baseQuery = fetchBaseQuery({
    baseUrl: `/api/${ baseUrl }`,
    prepareHeaders: (headers) => {
      // By default, if we have a token in the store, let's use that for authenticated requests
      const token = getFromLocalStorage(LOCAL_STORAGE_DATA_KEY.idToken);

      if (token) {
        headers.set('Authorization', token);
      }
      return headers;
    },
  });

  if (retries) {
    return retry(baseQuery, { maxRetries: retries - 1 });
  }


  return baseQuery;
};

export const baseAdminQueryWithReauth = (props: BaseQueryPropTypes) => {
  const fn: BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError> = async (
    args,
    api,
    extraOptions
  ): Promise<any> => {
    const result = await createBaseQuery(props)(args, api, extraOptions);

    if (result.error?.status === Status.FORBIDDEN) {
      store.dispatch(setForbidden(true));
      return result;
    }

   // additional checks for auth_token and refresh_token logic

    return result;
  };

  return fn;
};

Packages versions

  • "@reduxjs/toolkit": "^1.7.2",
  • "react-redux": "^7.2.6",

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions