I have two endpoints:
GET /api/messages/:userId/latest
and
GET /api/messages/:userId/:page
When the application loads a screen then, it calls the first endpoint to get information which pages have to loaded for a specific users, for example:
{
pages: [324, 325, 326]
}
and then, the second endpoint is called several times with parameters taken from the first endpoint.
My question is: How to define a query in Redux-Toolkit (RTK) Query which calls the endpoints in this way and then merges the results?
My code snippets:
export interface MessageApiParams {
userId: String | undefined,
page: number
}
export const baseQuery = fetchBaseQuery({
baseUrl: '/api',
prepareHeaders: (headers) => {
const token = getAccessToken()?.token
if (token) {
headers.set("authorization", `Bearer ${token}`);
}
return headers;
},
})
export const messagesApi = createApi({
reducerPath: 'messagesApi',
baseQuery: baseQuery,
endpoints: builder => ({
getMessages: builder.query<Messages, MessageApiParams>({
query: (params: MessageApiParams) => {
return ({
url: `/users/${params.userId}/messages/${params.page}`,
method: 'GET',
headers: { Authorization: `Bearer ${getAccessToken()?.token}`}
});
}
})
})
})
You can combine multiple requests in a single custom query function.
Example could look something like the following:
export interface MessageApiParams {
userId: String | undefined;
}
export interface MessagesApiResult {
pages: number[];
messages: MessageOrError[];
}
export const messagesApi = createApi({
reducerPath: 'messagesApi',
baseQuery,
endpoints: builder => ({
getMessages: builder.query<MessagesApiResult, MessageApiParams>({
queryFn: async(
{ userId }: MessageApiParams,
api,
extraOptions,
baseQuery
) => {
// Fetch latest messages from endpoint #1 "/api/messages/:userId/latest"
const messagesResult = await baseQuery({
url: `/messages/${userId}/latest`,
method: 'GET',
});
if (messagesResult.error) {
return {
error: messagesResult.error as /* your base query error type here */
};
}
const pages = messagesResult as number[];
// Fetch pages from endpoint #2 "/api/messages/:userId/:page"
const pagesResults = await Promise.all(pages.map(
page => baseQuery({
url: `/messages/${userId}/${page}`,
method: 'GET',
})
));
return {
data: {
pages,
messages: pagesResults
} as MessagesApiResult;
};
},
}),
}),
});