Created
August 11, 2019 21:53
-
-
Save codingmatty/87fa40f3618a1fc8638c74e89d52cb73 to your computer and use it in GitHub Desktop.
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 { useEffect, useState } from 'react'; | |
/** | |
* Usage: | |
* | |
* const {response, error, loading} = useFetch({ url, ...options }, deps); | |
*/ | |
export default function useFetch( | |
{ | |
url, | |
method = 'GET', | |
body, | |
onFetchStart = () => {}, | |
onFetchComplete = () => {}, | |
onSuccess = () => {}, | |
onFailure = () => {}, | |
shouldFetch = method === 'GET', | |
json, | |
...miscFetchOptions | |
}, | |
deps = [] | |
) { | |
const [loading, setLoading] = useState(true); // Loading state true for SSR | |
const [response, setResponse] = useState(); | |
const [error, setError] = useState(); | |
// Wrap fetch in useEffect so it doesn't happen on SSR | |
const fetchData = async (data) => { | |
await onFetchStart(); | |
setLoading(true); | |
setError(); | |
try { | |
if (typeof json === 'string') { | |
body = JSON.stringify({ ...JSON.parse(json), ...data }); | |
} else if (typeof json === 'object') { | |
body = JSON.stringify({ ...json, ...data }); | |
} | |
const response = await fetch(url, { | |
...miscFetchOptions, | |
method, | |
headers: { | |
'Content-Type': json && 'application/json' | |
}, | |
body | |
}); | |
const contentType = response.headers.get('content-type') || ''; | |
if (!contentType.includes('application/json')) { | |
if (response.status === 204) { | |
await onSuccess(); | |
setResponse(); | |
} else { | |
// This assumes the response should be JSON and textual response would mean an error | |
throw new Error(await response.text()); | |
} | |
} else { | |
const responseJson = await response.json(); | |
if (responseJson.errors) { | |
const jsonResponseError = new Error('JSON Error Response'); | |
jsonResponseError.errors = responseJson.errors; | |
throw jsonResponseError; | |
} else { | |
await onSuccess(responseJson); | |
setResponse(responseJson); | |
} | |
} | |
} catch (error) { | |
await onFailure(error); | |
setError({ | |
message: 'Fetch Error', | |
value: error.message, | |
error | |
}); | |
} finally { | |
setLoading(false); | |
await onFetchComplete(); | |
} | |
}; | |
useEffect( | |
() => { | |
if (shouldFetch) { | |
fetchData(); | |
} | |
}, | |
// Run effect when url or options change. | |
[url, body, shouldFetch, ...deps] | |
); | |
return { response, error, loading, fetchData }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment