import React , { useContext , useReducer , useEffect } from 'react' ; import { api } from 'ProjectPlanner/api' ; import { User } from 'ProjectPlanner/types' ; export type AuthContextActions = { type : 'LOGIN' ; user : User ; } | { type : 'LOGOUT' ; } ; type State = { authenticated : null | boolean ; user : null | User ; } ; type Context = State & { login ( user ) : void ; logout ( ) : void ; } ; const AuthStateContext = React . createContext < Context | null > ( null ) ; export const AuthProvider = ( { children } ) => { const [ state , dispatch ] = useReducer ( ( state , action ) => { switch ( action . type ) { case 'LOGIN' : { return { authenticated : true , user : action . user } ; } case 'LOGOUT' : { return { user : null , authenticated : false } ; } default : return state ; } } , { authenticated : null , user : null , } ) ; const login = ( user ) => { dispatch ( { type : 'LOGIN' , user } ) ; } ; const logout = ( ) => { dispatch ( { type : 'LOGOUT' } ) ; } ; useEffect ( ( ) => { let isCurrent = true ; api . auth . getAuthenticatedUser ( ) . then ( ( user ) => { if ( user && isCurrent ) { login ( user ) ; } else { logout ( ) ; } } ) ; return ( ) => { isCurrent = false ; } ; } , [ ] ) ; const context = { ... state , login , logout , } ; return < AuthStateContext . Provider value = { context } children = { children } / > ; } ; export function useAuth ( ) { const context = useContext ( AuthStateContext ) ; if ( ! context ) { throw Error ( 'Use of useAuth is outside of Provider' ) ; } return context ; }