import { useReducer, useCallback } from 'react' type State = { loading: boolean error: E | null } type Action = | { type: 'start loading' | 'stop loading' | 'clear error' } | { type: 'new error' error: E } const createReducer = () => ( state: State, action: Action ): State => { switch (action.type) { case 'clear error': return { ...state, error: null, } case 'new error': return { ...state, error: action.error, } case 'start loading': return { ...state, loading: true, } case 'stop loading': return { ...state, loading: false, } default: return state } } export const useNetworkReducer = ( state?: State ) => { const [s, dispatch] = useReducer( createReducer(), state ?? { loading: false, error: null, } ) const { loading, error } = s const setLoading = useCallback( (loading: boolean) => dispatch({ type: loading ? 'start loading' : 'stop loading' }), [dispatch] ) const setError = useCallback( (error: E | null) => error ? dispatch({ type: 'new error', error }) : dispatch({ type: 'clear error' }), [dispatch] ) return { loading, error, setLoading, setError, dispatch, } }