I’m trying to implement user state management with tanstack query instead of using react context. Right now i can log in and im redirected successfuly to my home page. However when i logout i invalidate the ‘user’ query key but no redirect is happening. It seems the my route rerender before the query key is invalidated.
Here is my ProtectRoute function
const ProtectRoute = () => {
const location = useLocation()
const { data: user, isLoading } = useQuery({
queryKey: ['user'],
queryFn: profile,
retry: false,
})
if (isLoading) return <div>...loading</div>
return user ? (
<Outlet />
) : (
<Navigate to="/signin" state={{ from: location }} replace />
)
}
Im calling it in my App.ts
function App() {
return (
<Routes>
<Route path="/" element={<Navigate to="/home" />} />
<Route element={<PublicRoute />}>
<Route path="/signin" element={<SignIn />} />
<Route path="/signup" element={<SignUp />} />
</Route>
<Route element={<ProtectRoute />}>
<Route path="/home" element={<Home />} />
</Route>
<Route path="/*" element={<Missing />} />
</Routes>
)
}
Here is how i try to logout
const Home = () => {
const navigate = useNavigate()
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: logout,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['user'] })
navigate('/signin', { replace: true })
},
})
const handleClick = () => {
mutation.mutate()
}
return (
<div>
<h1>Home</h1>
<button onClick={handleClick}>logout</button>
</div>
)
}
Here is my SignIn component:
const SignIn = () => {
const navigate = useNavigate()
const location = useLocation()
const from = location.state?.from?.pathname || '/'
const {
register,
handleSubmit,
setError,
formState: { errors },
} = useForm<SignInForm>({
defaultValues: {
email: '',
password: '',
},
})
const mutation = useMutation({
mutationFn: (payload: SignInPayload) => login(payload),
onSuccess: () => navigate(from, { replace: true }),
onError: (error) => {
if (error instanceof AxiosError) {
const { data } = error.response?.data // response data
const message = data ? data.error.message : 'Something went wrong'
setError('root', { type: 'custom', message })
}
},
})
const onSubmit = (data: SignInForm) => {
mutation.mutate(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
...
</div>
)
}
What I have tried:
I already tried to await the queryClient.invalidateQueries with no success. I also believe it should work without manually navigating after the invalidation.
Expected Behavior:
When the logout is successful, the ProtectRoute component should redirect to the /signin page automatically once the user query is invalidated.
Actual Behavior:
No redirection is happening after logging out. It seems that my route re-renders before the query key is invalidated and the user state is reseted.