Skip to content

Instantly share code, notes, and snippets.

@Nyalab
Created April 15, 2019 08:38
Show Gist options
  • Select an option

  • Save Nyalab/44b8ae3799d74b74407377dfde0ca5bb to your computer and use it in GitHub Desktop.

Select an option

Save Nyalab/44b8ae3799d74b74407377dfde0ca5bb to your computer and use it in GitHub Desktop.
import {useContext, useEffect, useReducer} from "react"
import FetcherContext from "~/components/fetcher.js"
import UserContext from "~/components/user.js"
const reducer = (state, action) => {
const {type, payload} = action
switch (type) {
case "SET_URL":
case "FETCH_INIT":
return {
...state,
...(payload && payload.url && {url: payload.url}),
data: null,
loading: true,
error: null,
}
case "FETCH_SUCCESS":
return {
...state,
data: payload.data,
loading: false,
error: null,
}
case "FETCH_FAILURE":
return {
...state,
data: null,
loading: false,
error: payload.error,
}
}
}
const useFetcher = (url, options) => {
let initialState = {
url: url || null,
loading: false,
data: null,
error: null,
}
const [state, dispatch] = useReducer(reducer, initialState)
const {api, options: fetchOptions} = useContext(FetcherContext)
const userContext = useContext(UserContext)
const setURL = url => dispatch({type: "SET_URL", payload: {url}})
const setURLAndFetch = url => {
dispatch({type: "SET_URL", payload: {url}})
doFetch()
}
const doFetch = async (url, options) => {
dispatch({type: "FETCH_INIT", ...(url && {payload: {url}})})
try {
const finalUrl = url ? url : state.url
const res = await fetch(`${api}${finalUrl}`, {
...fetchOptions,
...options,
})
for (const [header, value] of res.headers) {
if (header.toLowerCase() === "x-auth") {
if (value !== "") {
const error = "AUTH_REQUIRED"
dispatch({type: "FETCH_FAILURE", payload: {error}})
userContext.setAuthFields(value.split(";"), finalUrl)
return
}
}
if (header.toLowerCase() === "x-authlastresult") {
if (value === "true") {
userContext.removeAuthFields()
}
}
}
const data = await res.json()
dispatch({type: "FETCH_SUCCESS", payload: {data}})
} catch (error) {
dispatch({type: "FETCH_FAILURE", payload: {error}})
}
}
useEffect(() => {
if (url) {
doFetch()
}
}, [url, options])
return {...state, setURL, setURLAndFetch, doFetch}
}
export default useFetcher
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment