Skip to content

Instantly share code, notes, and snippets.

@alexandrius
Created June 17, 2023 21:23
Show Gist options
  • Save alexandrius/d90fa0ed172ddf5b25b75dfd664f8bb1 to your computer and use it in GitHub Desktop.
Save alexandrius/d90fa0ed172ddf5b25b75dfd664f8bb1 to your computer and use it in GitHub Desktop.
use-fetch-hook
import { baseUrl } from 'env';
function handleResponse(response) {
return response.text().then((text) => {
const data = text && JSON.parse(text);
if (!response.ok) {
const error = (data && data.error) || response.statusText;
return Promise.reject(error);
}
return data;
});
}
function handleError(error) {
return Promise.reject(error);
}
function _fetch(endpoint, requestOptions) {
return fetch(`${baseUrl}${endpoint}`, requestOptions).then(handleResponse).catch(handleError);
}
function getEndpointWithParams(endpoint, params) {
let endpointWithParams = endpoint;
if (params) {
// eslint-disable-next-line no-undef
const urlSearchParams = new URLSearchParams(params);
endpointWithParams += `?${urlSearchParams.toString()}`;
}
return endpointWithParams;
}
function get({ endpoint, params, signal }) {
const requestOptions = {
method: 'GET',
signal,
};
return _fetch(getEndpointWithParams(endpoint, params), requestOptions);
}
function post({ endpoint, params, body, signal }) {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal,
};
return _fetch(getEndpointWithParams(endpoint, params), requestOptions);
}
function put({ endpoint, params, body, signal }) {
const requestOptions = {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal,
};
return _fetch(getEndpointWithParams(endpoint, params), requestOptions);
}
function del({ endpoint, signal }) {
const requestOptions = {
method: 'DELETE',
signal,
};
return _fetch(endpoint, requestOptions);
}
export { get, post, put, del };
import { useCallback, useEffect, useRef, useState } from 'react';
import * as methods from './fetch';
export default function useFetch({ endpoint, params, body, method, requestOnMount = true }) {
// eslint-disable-next-line no-undef
const abortController = useRef(new AbortController()).current;
const request = useCallback(() => {
const { signal } = abortController;
methods[method]({ endpoint, signal, params, body })
.then((response) => {
setRequestState((state) => ({ ...requestState, loading: false, response }));
})
.catch((error) => setRequestState((state) => ({ ...requestState, loading: false, error })));
}, []);
const [requestState, setRequestState] = useState({
error: null,
response: null,
request,
loading: requestOnMount,
});
useEffect(() => {
if (requestOnMount) {
request();
}
return () => {
abortController.abort();
};
}, []);
return requestState;
}
export function useGet(endpoint, params) {
return useFetch({ endpoint, ...params, method: 'get' });
}
export function usePost(endpoint, body, params) {
return useFetch({ endpoint, body, ...params, method: 'post' });
}
export function usePut(endpoint, body, params) {
return useFetch({ endpoint, body, ...params, method: 'put' });
}
export function useDelete(endpoint, params) {
return useFetch({ endpoint, ...params, method: 'del' });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment