I’m using Redux-Toolkit (RTK) Query with fetchBaseQuery
and a custom baseQueryWithReauth
function for handling authentication. My setup involves checking for authentication and refreshing tokens if necessary.
Here's the relevant code:
baseQuery.js
import { fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { authApiSlice } from "~/features/api/authApiSlice";
// Create a base query instance
const baseQuery = fetchBaseQuery({
baseUrl: import.meta.env.VITE_API_BASE_URL,
credentials: "include",
prepareHeaders: (headers) => {
headers.set("x-api-key", localStorage.getItem("apiKey") || '');
return headers;
},
});
const baseQueryWithReauth = async (args, api, extraOptions) => {
console.log('Base Query Args:', args);
console.log('Extra Options:', extraOptions);
const shouldSkipAuth = extraOptions?.skipAuth || false;
let result = await baseQuery(args, api, extraOptions);
if (!shouldSkipAuth && result.error && result.error.status === 401) {
const refreshResult = await api.dispatch(
authApiSlice.endpoints.refreshToken.initiate()
);
if (refreshResult.data) {
result = await baseQuery(args, api, extraOptions);
} else {
return refreshResult;
}
}
return result;
};
export { baseQueryWithReauth as baseQuery };
authApiSlice.js
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQuery } from "~/services/api/baseQuery";
export const authApiSlice = createApi({
reducerPath: "authApi",
baseQuery,
endpoints: (builder) => ({
login: builder.mutation({
query: ({ email, password }) => ({
url: `/auth/login`,
method: "POST",
body: { email, password },
extraOptions: { skipAuth: true }, // Skip auth for login
}),
}),
refreshToken: builder.mutation({
query: () => ({
url: `/auth/refresh-token`,
method: "POST",
}),
}),
}),
});
export const { useLoginMutation } = authApiSlice;
Login.jsx
const [login] = useLoginMutation();
const handleLogin = async (email, password) => {
try {
const result = await login({ email, password }).unwrap();
console.log('Login result:', result);
} catch (err) {
console.error('Login error:', err);
}
};
What I Tried
extraOptions
in baseQueryWithReauth
to verify if it’s being passed correctly.extraOptions
in the authApiSlice
endpoints, specifically for the login endpoint to skip authentication.What I Expected
extraOptions
set for the login request would be available in the baseQueryWithReauth function, allowing it to skip the authentication logic for login requests.extraOptions
is undefined in baseQueryWithReauth
, which causes issues while login.The extraOptions
are passed to the endpoint defintion, not the endpoint's query
or queryFn
property.
export const authApiSlice = createApi({
reducerPath: "authApi",
baseQuery,
endpoints: (builder) => ({
login: builder.mutation({
query: ({ email, password }) => ({
url: `/auth/login`,
method: "POST",
body: { email, password },
// <-- remove from here
}),
extraOptions: { skipAuth: true }, // <-- move to here
}),
refreshToken: builder.mutation({
query: () => ({
url: `/auth/refresh-token`,
method: "POST",
}),
}),
}),
});