Errors are returned before being able to redirect
IGassmann opened this issue · comments
Describe the bug
I have an app that uses Clerk and the authExchange
for authentication.
'use client';
import { useMemo } from 'react';
import { useAuth } from '@clerk/nextjs';
import { authExchange } from '@urql/exchange-auth';
import { Provider, cacheExchange, createClient, fetchExchange, mapExchange } from 'urql';
export default function URQLProvider({ children }: { children: React.ReactNode }) {
const { getToken, isSignedIn, signOut } = useAuth();
const urqlClient = useMemo(() => {
return createClient({
url: '/api',
exchanges: [
cacheExchange,
mapExchange({
onError(error) {
const isAuthError = error.response.status === 401;
if (isAuthError) {
signOut(); // This internally performs a redirect to the sign-in page with Next.js' router.push('/sign-in') function.
// window.location.href = '/sign-in'; also doesn't work
// router.push('/sign-in'); neither does this
}
},
}),
authExchange(async (utils) => {
let sessionToken = await getToken();
return {
addAuthToOperation: (operation) => {
if (!sessionToken) return operation;
return utils.appendHeaders(operation, {
Authorization: `Bearer ${sessionToken}`,
});
},
didAuthError: (error) => error.response.status === 401,
refreshAuth: async () => {
sessionToken = await getToken({ skipCache: true });
},
};
}),
fetchExchange,
],
});
}, [getToken, isSignedIn]);
return <Provider value={urqlClient}>{children}</Provider>;
}
Whenever a user signs out, all useQuery
hooks on the page return an Unauthorized
error for a brief moment before being redirected to the sign-in page.
The user needs to be redirected before seeing any error caused by the sign-out.
Reproduction
https://github.com/IGassmann/urql-clerk-signout
Urql version
urql v4.0.6
Validations
- I can confirm that this is a bug report, and not a feature request, RFC, question, or discussion, for which GitHub Discussions should be used
- Read the docs.
- Follow our Code of Conduct
I mean, that's expected behavior as signing out and re-initializing the client forces us to re-evaluate the queries. You can however add pause: ifNoToken
to the useQuery
so they don't run when they are expected to return unauthorized due to i.e. a missing token. or not render anything if there is no auth-token which I think is something you most likely don't want
We still wanted to render children
to perform operations without authentication in certain cases.
We solved the issue by adding a retryExchange
after authExchange
.