Created
October 20, 2020 14:25
-
-
Save mpriour/69cea28ae7a5bb10f6a08587309ef309 to your computer and use it in GitHub Desktop.
async reducer example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Context, createContext, h } from "preact"; | |
import { useMemo } from "preact/hooks"; | |
import { UserSession } from "@esri/arcgis-rest-auth"; | |
import useLocalStorageState from "../hooks/useLocalStorageState"; | |
import useAsyncReducer from "../hooks/useAsyncReducer"; | |
interface IProviderProps { | |
children?:any | |
} | |
enum AuthActions { | |
read = 'READ_SESSION', | |
write = 'WRITE_SESSION', | |
start = 'START_SESSION', | |
end = 'END_SESSION' | |
} | |
type AuthActionTypes = keyof typeof AuthActions | |
interface IContextProps { | |
auth: UserSession, | |
dispatch: (action: AuthActionTypes) => Promise<void> | |
} | |
const authReducer = (state: UserSession, action: AuthActionTypes) => { | |
const [serializedSession, setSerializedSession] = useLocalStorageState('_AGO_SESSION_', null) | |
switch (action) { | |
case "read": | |
if(serializedSession){ | |
// If there is a serialized session, parse it and set state | |
let parsed = JSON.parse(serializedSession) | |
// Cast the tokenExpires property back into a date. | |
parsed.tokenExpires = new Date(parsed.tokenExpires) | |
return new Promise<UserSession>(resolve => {resolve(new UserSession(parsed))}) | |
} | |
return new Promise<UserSession>((resolve, reject)=>{reject('Saved session not available')}) | |
case "write": | |
const serialized = state.serialize() | |
setSerializedSession(serialized) | |
return new Promise<UserSession>(resolve => {resolve(state)}) | |
case "start": | |
if(serializedSession){ | |
// If there is a serialized session, parse it and set state | |
let parsed = JSON.parse(serializedSession) | |
// Cast the tokenExpires property back into a date. | |
parsed.tokenExpires = new Date(parsed.tokenExpires) | |
if(parsed.tokenExpires > new Date()){ | |
return new Promise<UserSession>(resolve => {resolve(new UserSession(parsed))}) | |
} | |
} | |
return UserSession.beginOAuth2({ | |
clientId: 'arcgisonline', | |
redirectUri: window.location.href, | |
portal: 'https://devext.arcgis.com/sharing/rest', | |
popup: false | |
}).then(session => { | |
setSerializedSession(session.serialize()) | |
return session | |
}) | |
case "end": | |
setSerializedSession(null) | |
return new Promise<UserSession>(resolve => {resolve({} as UserSession)}) | |
default: | |
return new Promise<UserSession>((resolve, reject) => {reject('No valid action specified')}) | |
} | |
} | |
const AuthContext = createContext({} as IContextProps) as Context<IContextProps> | |
function AuthProvider({children}: IProviderProps){ | |
const [auth, dispatch] = useAsyncReducer<UserSession,AuthActionTypes>(authReducer, {} as UserSession) | |
const contextObj = useMemo(()=>({auth, dispatch} as IContextProps), [auth]) | |
return ( | |
<AuthContext.Provider value={contextObj}> | |
{children} | |
</AuthContext.Provider> | |
) | |
} | |
export {AuthContext, AuthProvider} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState } from "preact/hooks" | |
function useAsyncReducer<S,A>(reducer:(prevState: S, action: A) => Promise<S>, initialState:S){ | |
const [state, setState] = useState<S>(initialState); | |
const dispatch = async (action:A) => { | |
const result = reducer(state, action); | |
if (typeof result.then === "function") { | |
try { | |
const newState = await result; | |
setState(newState); | |
} catch (err) { | |
setState({ ...state, error: err }); | |
} | |
}/* else { | |
setState(result as S); | |
} */ | |
}; | |
return [state, dispatch]; | |
}; | |
export default useAsyncReducer; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment