I am using zustand and mmkv with tanstack query in my react native app. The issue i am facing is i am setting the access token when the user logs in and i remove the auth stack from navigation and mounts the further stack.
The home screen is mounted first where an API call is made which requires access token, which i am saving to mmkv storage, but when the home page API is made i am unable to get the token, when closing the app and reopening then the token arrives or if i refresh the app. There is some lag in getting from storage i guess.
Heres my code:
Zustand Part:
import {createAuthSlice, IAuthSlice} from '@authScreens/Slice/UserAuthSlice';
import {create} from 'zustand';
import {createJSONStorage, persist} from 'zustand/middleware';
import {zustandStorage} from '@store/MMKVConfig';
interface IStore extends IAuthSlice {}
export const appStore = create<IStore>()(
persist(
(set, get, api) => ({
...createAuthSlice(set, get, api),
}),
{
name: 'auth-storage',
storage: createJSONStorage(() => zustandStorage),
},
),
);
Slice:
export interface IAuthSlice {
isOnboarded: boolean;
isLoggedIn: boolean;
user: Partial<Data>;
registeredUserdata: IUserRegisterResponse;
setIsOnboarded: (data: boolean) => void;
setIsLoggedIn: (data: LoginResponse) => Promise<void>;
setUserRegistration: (data: UserRegisterResponse) => void;
setIsLoggedOut: () => void;
}
export const createAuthSlice: StateCreator<IAuthSlice> = set => {
return {
isOnboarded: false,
isLoggedIn: false,
user: {} as Partial<Data>,
registeredUserdata: {} as IUserRegisterResponse,
setIsOnboarded: (data: boolean): void => {
set({isOnboarded: data});
},
setIsLoggedIn: async (data: LoginResponse): Promise<void> => {
set({user: data?.data, isLoggedIn: true});
},
setUserRegistration: (data: UserRegisterResponse): void => {
set({registeredUserdata: data.data});
},
setIsLoggedOut: (): void => {
set({isLoggedIn: false});
set({user: {} as Data});
},
};
};
Here i am calling the set setIsLoggedIn Method at login screen:
const onSubmit = async (data: ILogin) => {
const response = (await mutateAsync(data)) as LoginResponse;
if (response?.status && response?.data?.access_token) {
setIsLoggedIn(response);
}
};
And my token injecting and networking call here:
export function useGetQuery(
props: Omit<IUseNetworkCallGetBase, 'axiosClient'>,
): UseQueryResult<any, Error> {
const {
method,
queryKey,
url,
persist,
enabled = false,
params = '',
select,
} = props;
//injecting token here
axiosClientLMS.interceptors.request.use(async config => {
if (access_token) {
config.headers.Authorization = `Bearer ${access_token}`;
}
return config;
});
const isReallyEnabled = !!(enabled && access_token);
const config = {
axiosClient: axiosClientLMS,
queryKey: queryKey,
method: method,
url: url,
persist: persist,
params: params,
enabled: isReallyEnabled,
select: select,
};
return useRTKQuery(config);
}