Created
October 23, 2019 19:49
-
-
Save takethefake/c56ed4a4e1465305455355ad448243ff to your computer and use it in GitHub Desktop.
This file contains hidden or 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 { useEffect, useReducer } from "react"; | |
export interface QueryArgs<T> { | |
url: string; | |
options: RequestInit; | |
deserialize?: (res: Response) => Promise<T>; | |
} | |
export interface QueryAction<T> { | |
type: string; | |
data: T; | |
error: Error; | |
} | |
export interface QueryState<T> { | |
data: T | null; | |
loading: boolean; | |
error: Error | null; | |
} | |
const initialState = { | |
data: null, | |
loading: false, | |
error: null | |
}; | |
const reducer = <T>() => (prevState: QueryState<T>, action: QueryAction<T>) => { | |
switch (action.type) { | |
case "START": | |
return { ...prevState, loading: true }; | |
case "SUCCESS": | |
return { ...prevState, data: action.data, loading: false }; | |
case "ERROR": | |
return { ...prevState, error: action.error, loading: false }; | |
default: | |
throw new Error(`Invalid action type ${action.type}`); | |
} | |
}; | |
export const jsonOptions = { | |
headers: { accept: "application/json" } | |
}; | |
export function useQuery<T>({ | |
url, | |
options = {}, | |
deserialize = res => res.json() | |
}: QueryArgs<T>) { | |
const typedReducer = reducer<T>(); | |
const [state, dispatch] = useReducer(typedReducer, initialState); | |
const refetch = async () => { | |
dispatch({ type: "START" } as QueryAction<T>); | |
try { | |
const res = await fetch(url, options); | |
const jsonData = await deserialize(res); | |
dispatch({ type: "SUCCESS", data: jsonData } as QueryAction<T>); | |
} catch (e) { | |
dispatch({ type: "ERROR", error: e } as QueryAction<T>); | |
} | |
}; | |
useEffect(() => { | |
if (!url) { | |
return; | |
} | |
(async () => { | |
await refetch(); | |
})(); | |
return () => {}; | |
}, [url, options]); | |
return { ...state, refetch }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment