Lucy Johnston
Lucy Johnston

Reputation: 43

RTK Query. How to handle path variable in baseUrl?

I need to make a request to a URL like this /common/path/:userId/specific/path/endpoints. /common/path is shared across many endpoints, and I don't want to put all of those queries in the same file. Ideally, I'd create a slice for /common/path/:userId/specific/path and its endpoints. I have userId when the store is created. Could I pass userId into the slice and put it in the baseUrl somehow?

Or am I approaching this wrong? Is there a better way? I can't change the structure of the URL.

EDIT: This is what I'm trying.

In MyFile.jsx

const store = configureStore({reducer: mySlice, userId})

In mySlice.js

export const mySlice = createApi({
    reducerPath: 'api',
    baseQuery: fetchBaseQuery({
        baseUrl: `/common/path/${state.userId}/specific/path`
    }),
    endpoints: {4 endpoints defined here}
})

But this doesn't work, because state and getState are not accessible when creating the baseUrl.

Upvotes: 1

Views: 41

Answers (1)

Drew Reese
Drew Reese

Reputation: 203333

But this doesn't work, because state and getState are not accessible when creating the baseUrl.

They are actually, but you need to create a custom baseQuery function.

See Implementing a custom baseQuery for details.

Create a base query function that accesses the Redux api to access the current state at the time a request is made to compute the desired baseUrl value that is then passed along to the actual fetchBaseQuery you are using.

Basic Example:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

const baseQuery = (baseQueryArgs = {}) => async (
  fetchArgs = {},
  api,
  extraOptions = {},
) => {
  const { getState } = api;
  const state = getState();
  const baseUrl = `/common/path/${state.userId}/specific/path`;

  return fetchBaseQuery({
    ...baseQueryArgs,
    baseUrl,
  })(fetchArgs, api, extraOptions);
};
export const mySlice = createApi({
  reducerPath: 'api',
  baseQuery: baseQuery(),
  endpoints: {/* 4 endpoints defined here */}
});

If you wanted this to be a little more robust you could pass a baseUrl string with some placeholder text that is replaced in baseQuery.

Example:

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

const baseQuery = (baseQueryArgs = {}) => async (
  fetchArgs = {},
  api,
  extraOptions = {},
) => {
  const { getState } = api;
  const state = getState();
  const baseUrl = baseQueryArgs.baseUrl.replace("{{userId}}", state.userId);

  return fetchBaseQuery({
    ...baseQueryArgs,
    baseUrl,
  })(fetchArgs, api, extraOptions);
};
export const mySlice = createApi({
  reducerPath: 'api',
  baseQuery: baseQuery({
    baseUrl: "/common/path/{{userId}}/specific/path",
  }),
  endpoints: {/* 4 endpoints defined here */}
});

Upvotes: 1

Related Questions