Search code examples
reduxreact-reduxredux-toolkitrtk-query

Redux ToolKIt Query getState on prepareHeaders show null on getState().auth.accessToken


Hello everyone so I have problem with my RTK Query where the prepareHeaders getState() not getting the value from the auth state. So I have accessToken state in my store where to store the value of the accessToken when user successfully login. But for some reason getState just won't get the value eventhought the value is already in store but still showing null in getState(). But if i call the function of login again which will dispatch accessToken value second time then the value will appear in getState(). But I don't know why is that happening. This is my code:

ApiSlice.js

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { setAccessToken, logOut } from "../slice/authSlice";

const baseQuery = fetchBaseQuery({ baseUrl: "http://127.0.0.1:8000" ,
  credentials: "include",
  prepareHeaders: (headers, { getState }) => {
      // Get the access token from your store
      const accessToken = getState().auth.accessToken
      console.log(accessToken)
      // console.log('Authorization', `Bearer ${accessToken}`)
      // If there is an access token, set the authorization header
      if (accessToken) {
        headers.set('Authorization', `Bearer ${accessToken}`);
      }
      return headers;
   }
});

userApiSlice.js

export const userApiSlice = apiSlice.injectEndpoints({
    endpoints: (builder) =>({
        userRegister: builder.mutation({
            query: (value) =>({
                url: "/register",
                method: "POST",
                body: value,
            })
        }),
        login : builder.mutation({
            query: (value) => ({
              url : "/login",
              method : "POST",
              body : value,
            }),
            invalidatesTags: ["Users"],
            onQueryStarted: async (value, { dispatch, queryFulfilled }) => {
                const { data } = await queryFulfilled;
                const accessToken = data.accessToken
                dispatch(setAccessToken(accessToken));
              },
          }),
    })
});

authSlice.js

const initialState = {
    accessToken: null,
}

const authSlice = createSlice({
    name : "auth",
    initialState,
    reducers:{
        setAccessToken: (state, action) =>{
            state.accessToken = action.payload;
        },
        logOut: ()=> initialState
    },

})

so if i call the login function here which is the login mutation login function

const [loginUser, { isLoading, isError, error}] = useLoginMutation();
  const navigate = useNavigate();

  const loginSubmit = async (value) => {
    const {accessToken} = await loginUser(value).unwrap();
    console.log(accessToken)
    navigate("/");
  };

So if I run this loginSubmit first time the accessToken will be store the authSlice.js accessToken but the getState().auth just wont get the value but the second call on the function loginSubmit that will send accessToken to the getState why is that? I just can't find the solution. Can someone help me?

Thanks you.


Solution

  • Not sure where the problem is in your code, on first glance looks valid. But normally you do that via extra reducer:

    const authSlice = createSlice({
      ...
      reducers:{
         ...
      },
      extraReducers: (builder) => {
      builder.addMatcher(
        userApiSlice.endpoints.login.matchFulfilled,
          (state, { payload }) => {
            state.accessToken = payload.accessToken
          }
        )
      },
    });
    

    idk, that the case, but this won't trigger if you have the response cached already...