T
TanStack•3y ago
old-apricot

My Mutation is stuck in loading state after successful request

Can't figure out what is going on here, made a POST request and it works fine. Im trying to do a GET Request now using a mutation with no luck. Just stuck in loading state. The data comes back fine and the request is successful, the state is just wrong .
No description
7 Replies
old-apricot
old-apricotOP•3y ago
Does useMutation just not work with GET requests?
graceful-blue
graceful-blue•3y ago
react query never cares about what kind of requests you make, it only cares about the Promise that gets retuned
old-apricot
old-apricotOP•3y ago
Okay cheers, must be something else going on then as my other requests work just not this GET one. Strange how they're all setup the same though. Most likely gonna be something super obvious. 😆 Yep sorted it, it was me. This is what I was doing:
if (session.token && !account) mutate(session.token);
if (session.token && !account) mutate(session.token);
Needed to wrap in a useEffect:
useEffect(() => {
if (session.token && !account) mutate(session.token);
}, [session.token, account, mutate]);
useEffect(() => {
if (session.token && !account) mutate(session.token);
}, [session.token, account, mutate]);
graceful-blue
graceful-blue•3y ago
If possible, make it part of an event handler rather than an effect
old-apricot
old-apricotOP•3y ago
Will do, thanks for the help
foreign-sapphire
foreign-sapphire•3y ago
Can you show the code?
old-apricot
old-apricotOP•3y ago
Sure
export const useLoginToken = () => {
return useHandleMutation(authService.loginSessionToken);
};

const useHandleMutation = <TData extends AxiosResponse<AccountAPI.GetResponse>, TValue extends unknown>(func: MutationFunction<TData, TValue>) => {
const setAccount = useSetAtom(accountWriteAtom);
const [, setLoading] = useLoading();
const queryClient = useQueryClient();
return useMutation((val: TValue) => func(val), {
mutationKey: ['account-auth'],
onError: (error) => {
console.error(error);
localStorage.removeItem('sessionToken');
setAccount(undefined);
},
onSuccess: (data) => {
queryClient.setQueryData(['account-auth'], data);
setAccount(data.data);
}
});
};
export const useLoginToken = () => {
return useHandleMutation(authService.loginSessionToken);
};

const useHandleMutation = <TData extends AxiosResponse<AccountAPI.GetResponse>, TValue extends unknown>(func: MutationFunction<TData, TValue>) => {
const setAccount = useSetAtom(accountWriteAtom);
const [, setLoading] = useLoading();
const queryClient = useQueryClient();
return useMutation((val: TValue) => func(val), {
mutationKey: ['account-auth'],
onError: (error) => {
console.error(error);
localStorage.removeItem('sessionToken');
setAccount(undefined);
},
onSuccess: (data) => {
queryClient.setQueryData(['account-auth'], data);
setAccount(data.data);
}
});
};
Then used in component:
const session = useSession();
const account = useAccount();
const { mutate, isLoading } = useLoginToken();

useEffect(() => {
if (session.token && !account) mutate(session.token);
}, [session.token, account, mutate]);

if (!session.token) return <LoginFormController />;

//if loggedIn false but token is set we should try to use token to login
if (!account || isLoading) return <Loading />;

//if we hit here we have a valid session and account
return <MainController />;
const session = useSession();
const account = useAccount();
const { mutate, isLoading } = useLoginToken();

useEffect(() => {
if (session.token && !account) mutate(session.token);
}, [session.token, account, mutate]);

if (!session.token) return <LoginFormController />;

//if loggedIn false but token is set we should try to use token to login
if (!account || isLoading) return <Loading />;

//if we hit here we have a valid session and account
return <MainController />;
I have multiple login methods so rather than duping code i created a wrapper for mutation since i know the response for all login routes is the same

Did you find this page helpful?