fix(dashboard-v2): fix race conditions on /login & /logout calls
This commit is contained in:
parent
8cdf0f86b2
commit
d3c252a0b0
|
@ -2,6 +2,7 @@ import { Link, navigate } from "gatsby";
|
|||
import styled from "styled-components";
|
||||
|
||||
import { screen } from "../../lib/cssHelpers";
|
||||
import { useUser } from "../../contexts/user";
|
||||
import { DropdownMenu, DropdownMenuLink } from "../DropdownMenu";
|
||||
import { CogIcon, LockClosedIcon, SkynetLogoIcon } from "../Icons";
|
||||
import { PageContainer } from "../PageContainer";
|
||||
|
@ -49,7 +50,22 @@ const NavBarBody = styled.nav.attrs({
|
|||
}
|
||||
`;
|
||||
|
||||
export const NavBar = () => (
|
||||
export const NavBar = () => {
|
||||
const { mutate: setUserState } = useUser();
|
||||
|
||||
const onLogout = async () => {
|
||||
try {
|
||||
await accountsService.post("logout");
|
||||
// Don't refresh user state from server, as it will now respond with UNAUTHORIZED
|
||||
// and user will be redirected to /auth/login with return_to query param (which we want empty).
|
||||
await setUserState(null, { revalidate: false });
|
||||
navigate("/auth/login");
|
||||
} catch {
|
||||
// Do nothing.
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<NavBarContainer>
|
||||
<PageContainer className="px-0">
|
||||
<NavBarBody>
|
||||
|
@ -78,11 +94,7 @@ export const NavBar = () => (
|
|||
partiallyActive
|
||||
/>
|
||||
<DropdownMenuLink
|
||||
onClick={async () => {
|
||||
await accountsService.post("logout");
|
||||
navigate("/auth/login");
|
||||
// TODO: handle errors
|
||||
}}
|
||||
onClick={onLogout}
|
||||
activeClassName="text-primary"
|
||||
className="cursor-pointer"
|
||||
icon={LockClosedIcon}
|
||||
|
@ -94,3 +106,4 @@ export const NavBar = () => (
|
|||
</PageContainer>
|
||||
</NavBarContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import useSWR from "swr";
|
||||
import useSWRImmutable from "swr/immutable";
|
||||
|
||||
import { UserContext } from "./UserContext";
|
||||
|
||||
export const UserProvider = ({ children }) => {
|
||||
const { data: user, error, mutate } = useSWR("user");
|
||||
const { data: user, error, mutate } = useSWRImmutable("user");
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -15,12 +15,15 @@ const redirectUnauthenticated = (key) =>
|
|||
});
|
||||
|
||||
const redirectAuthenticated = (key) =>
|
||||
fetch(`${baseUrl}/${key}`).then((response) => {
|
||||
if (response.status === StatusCodes.OK) {
|
||||
navigate(`/`);
|
||||
fetch(`${baseUrl}/${key}`).then(async (response) => {
|
||||
if (response.ok) {
|
||||
await navigate("/");
|
||||
return response.json();
|
||||
}
|
||||
|
||||
return response.json();
|
||||
// If there was an error, let's throw so useSWR's "error" property is populated instead "data".
|
||||
const data = await response.json();
|
||||
throw new Error(data?.message || `Error occured when trying to fetch: ${key}`);
|
||||
});
|
||||
|
||||
export const allUsers = {
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
import { useEffect } from "react";
|
||||
import { navigate } from "gatsby";
|
||||
|
||||
import AuthLayout from "../../layouts/AuthLayout";
|
||||
|
||||
import { LoginForm } from "../../components/forms";
|
||||
import { useUser } from "../../contexts/user";
|
||||
|
||||
const LoginPage = ({ location }) => {
|
||||
const { user, mutate: refreshUserState } = useUser();
|
||||
const query = new URLSearchParams(location.search);
|
||||
const redirectTo = query.get("return_to");
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
navigate(redirectTo || "/");
|
||||
}
|
||||
}, [user, redirectTo]);
|
||||
|
||||
return (
|
||||
<div className="bg-white px-8 py-10 md:py-32 lg:px-16 xl:px-28 min-h-screen">
|
||||
<div className="mb-4 md:mb-16">
|
||||
<img src="/images/logo-black-text.svg" alt="Skynet" />
|
||||
</div>
|
||||
<LoginForm onSuccess={() => navigate(redirectTo || "/")} />
|
||||
<LoginForm
|
||||
onSuccess={async () => {
|
||||
await refreshUserState();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Reference in New Issue