- {user!.name}{' '}
+ {user.name}{' '}
Log out
diff --git a/src/components/Authentication/AuthenticationContext.ts b/src/components/Authentication/AuthenticationContext.ts
index 4e0f362..bac9ad6 100644
--- a/src/components/Authentication/AuthenticationContext.ts
+++ b/src/components/Authentication/AuthenticationContext.ts
@@ -6,20 +6,19 @@ export type User = {
email?: string;
};
-export type AuthState = {
- isLoggedIn: boolean | null;
+export type AuthenticationContextProps = {
user: User | null;
/**
* Function that can be used to trigger an auth state refresh.
*/
- refreshAuthState: (() => void) | null;
+ refresh: () => void;
};
-const AuthenticationContext = createContext
({
- isLoggedIn: false,
+const AuthenticationContext = createContext({
user: null,
- refreshAuthState: null,
+ refresh: () =>
+ console.warn('calling refresh on default AuthenticationContext'),
});
export default AuthenticationContext;
diff --git a/src/components/Authentication/AuthenticationWrapper.tsx b/src/components/Authentication/AuthenticationWrapper.tsx
index d438d1f..f367800 100644
--- a/src/components/Authentication/AuthenticationWrapper.tsx
+++ b/src/components/Authentication/AuthenticationWrapper.tsx
@@ -1,45 +1,30 @@
import { useCallback, useEffect, useState } from 'react';
import { getMe } from '../api';
-import AuthenticationContext, { AuthState } from './AuthenticationContext';
+import AuthenticationContext, { User } from './AuthenticationContext';
export default function AuthenticationWrapper({
children,
}: {
children: React.ReactNode;
}) {
- const sessionToken = localStorage.getItem('session_token');
// Prevent race conditions
- const [authState, setAuthState] = useState({
- isLoggedIn: null,
- user: null,
- refreshAuthState: null,
- });
+ const [user, setUser] = useState(null);
- const refreshAuthState = useCallback(() => {
- const loggedOut = () =>
- setAuthState({ isLoggedIn: false, user: null, refreshAuthState });
+ const refresh = useCallback(() => {
+ const none = () => setUser(null);
+ const sessionToken = localStorage.getItem('session_token');
if (sessionToken) {
- getMe()
- .then((user) => {
- if (user) {
- setAuthState({ isLoggedIn: true, user, refreshAuthState });
- } else {
- loggedOut();
- }
- })
- .catch(loggedOut);
+ getMe().then(setUser).catch(none);
} else {
- loggedOut();
+ none();
}
- }, [sessionToken]);
+ }, []);
- useEffect(() => {
- refreshAuthState();
- }, [refreshAuthState]);
+ useEffect(refresh, [refresh]);
return (
-
+
{children}
);
diff --git a/src/components/Authentication/Authenticator.tsx b/src/components/Authentication/Authenticator.tsx
index 83f9313..58ad628 100644
--- a/src/components/Authentication/Authenticator.tsx
+++ b/src/components/Authentication/Authenticator.tsx
@@ -3,45 +3,51 @@ import { Redirect, useLocation, useParams } from 'react-router-dom';
import AuthenticationContext from './AuthenticationContext';
import { createSession } from './createSession';
+function useCode() {
+ const location = useLocation();
+ const query = new URLSearchParams(location.search);
+ const code = query.get('code');
+
+ return code;
+}
+
export default function Authenticator() {
const { provider } = useParams<{ provider: string }>();
- const query = new URLSearchParams(useLocation().search);
- const code = query.get('code');
- const { refreshAuthState } = useContext(AuthenticationContext);
- const [status, setStatus] =
- useState<'pending' | 'errored' | 'authenticated'>('pending');
+ const code = useCode();
+ const { refresh } = useContext(AuthenticationContext);
+
+ const [pending, setPending] = useState(true);
const [token, setToken] = useState(null);
useEffect(() => {
+ if (token) {
+ localStorage.setItem('session_token', token);
+ } else {
+ localStorage.removeItem('session_token');
+ }
+ }, [token]);
+
+ useEffect(() => {
+ setPending(true);
createSession(code!)
- .then((data) => {
- if (data.status === 'success') {
- console.log('Success! Token:', data.token);
- setToken(data.token);
- localStorage.setItem('session_token', data.token);
- setStatus('authenticated');
- } else {
- console.log('Authentication failure.');
- setToken(null);
- localStorage.removeItem('session_token');
- setStatus('errored');
- }
+ .then(({ token }) => {
+ setToken(token ?? null);
})
- .catch(() => {
- setStatus('errored');
- });
+ .finally(() => setPending(false));
}, [code, provider]);
useEffect(() => {
- refreshAuthState && refreshAuthState();
- }, [token, refreshAuthState]);
+ refresh();
+ }, [token, refresh]);
- switch (status) {
- case 'authenticated':
- return ;
- case 'errored':
- return Sign In Error
;
- case 'pending':
- return Signing In
;
+ if (pending) {
+ return Signing In
;
}
+
+ if (token) {
+ return ;
+ }
+
+ // If we aren't pending anymore, but don't have a token, we must have errored
+ return Sign In Error
;
}