I use uswSWR to handle user authentication:
export function useAuthenticatedUser() {
const { data, error, isLoading, mutate } = useSWR("user",
UserApi.getAuthenticatedUser,
{
shouldRetryOnError(err) {
return !(err instanceof UnauthorizedError)
},
}
);
return {
user: data,
userLoading: isLoading,
userLoadingError: error,
mutateUser: mutate,
}
}
Because of SWR's automatic revalidation, this user is fetched again when a browser window or tab gains focus.
Problem: Revalidation doesn't work after logging out:
const { mutateUser } = useAuthenticatedUser();
async function logout() {
try {
await UserApi.logout();
mutateUser(undefined);
} catch (error) {
console.error(error);
alert(error);
}
}
This recording shows the problem in action. Note that the window gaining focus revalidates after logging in but not after logging out.
The problem was that I didn't return null if the user was not logged in. Logout propagates properly if I mutate with null
instead of undefined
.
export function useAuthenticatedUser() {
const { data, error, isLoading, mutate } = useSWR("user",
async () => {
try {
return await UsersApi.getAuthenticatedUser();
} catch (error) {
if (error instanceof UnauthorizedError) {
return null;
} else {
throw error;
}
}
}
);
return {
user: data,
userLoading: isLoading,
userLoadingError: error,
mutateUser: mutate,
}
}
Now mutate
accepts null
:
const { mutateUser } = useAuthenticatedUser();
async function logout() {
try {
await UserApi.logout();
mutateUser(null); // undefined won't propagate between tabs
} catch (error) {
console.error(error);
alert(error);
}
}