Skip to content

Instantly share code, notes, and snippets.

@intrnl
Last active November 24, 2023 04:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intrnl/574b2afea4b7a07425abf501ad2bcad0 to your computer and use it in GitHub Desktop.
Save intrnl/574b2afea4b7a07425abf501ad2bcad0 to your computer and use it in GitHub Desktop.
import { useState, useEffect } from 'preact/hooks'
/**
* @param {RequestInfo} url
* @param {RequestInit} opts
* @returns {useFetchObject}
*/
function useFetch (url, opts) {
const [response, setResponse] = useState(undefined)
const [error, setError] = useState(undefined)
const [isFetching, setIsFetching] = useState(true)
useEffect(() => {
const controller = new AbortController
let cancel = false
const getResponse = async () => {
setResponse(undefined)
setError(undefined)
setIsFetching(true)
try {
const resp = await fetch(url, {
...opts,
signal: controller.signal,
})
if (cancel) return
if (!resp.ok) throw resp
const type = resp.headers.get('content-type')
let data
if (type && type.includes('application/json')) {
data = await resp.json()
} else {
data = await resp.text()
}
if (cancel) return
setResponse(data)
setIsFetching(false)
} catch (err) {
if (cancel) return
setError(err)
}
}
getResponse()
return () => {
cancel = true
controller.abort()
}
}, [url, opts])
return {
response,
error,
isFetching,
}
}
export default useFetch
/**
* @typedef {object} useFetchObject
* @property {Response} response
* @property {Error} error
* @property {boolean} isFetching
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment