Skip to content

Instantly share code, notes, and snippets.

@neysidev
Created August 22, 2022 12:30
Show Gist options
  • Select an option

  • Save neysidev/b8fd0f5dc9f3bd210f533ed18df33490 to your computer and use it in GitHub Desktop.

Select an option

Save neysidev/b8fd0f5dc9f3bd210f533ed18df33490 to your computer and use it in GitHub Desktop.

Revisions

  1. neysidev created this gist Aug 22, 2022.
    77 changes: 77 additions & 0 deletions use-api-request.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    import { useState } from "react";
    const { REACT_APP_API_URL, REACT_APP_API_VERSION } = process.env;

    const buildUrl = (pathname, query) => {
    const apiUrl = `${REACT_APP_API_URL}api/v${REACT_APP_API_VERSION}`;
    const url = new URL(apiUrl + pathname);

    Object.keys(query).forEach(queryKey =>
    url.searchParams.set(queryKey, query[queryKey].toString())
    );

    return url.toString();
    };

    export function useApiRequest(
    endpoint,
    {
    query = {},
    method = "GET", // GET, POST, PUT, DELETE
    headers,
    body = undefined,
    responseType = "json", // json, text, blob, arraybuffer, document
    } = {}
    ) {
    const [result, setResult] = useState(null);
    const [error, setError] = useState(null);
    const [status, setStatus] = useState(null);
    const [loading, setLoading] = useState(false);

    const controller = new AbortController();

    const fetchData = () => {
    const isJson = responseType === "json";
    const auth = localStorage.getItem("auth");
    const url = buildUrl(endpoint, query);

    const reqHeaders = new Headers();
    if (auth) reqHeaders.append("Authorization", `Bearer ${auth}`);
    if (isJson) reqHeaders.append("Content-Type", "application/json");
    if (headers)
    Object.entries(headers).forEach(([key, value]) =>
    reqHeaders.append(key, value)
    );

    setLoading(true);
    fetch(url, {
    method,
    headers: reqHeaders,
    body: body && isJson ? JSON.stringify(body) : body,
    signal: controller.signal,
    })
    .then(async res => {
    const parsed = await res[responseType]();
    setStatus(res.status);
    setResult(parsed.result || parsed.data);
    })
    .catch(err => {
    setStatus(err.status);
    setError(err);
    })
    .finally(() => {
    setLoading(false);
    });
    };

    const cancelFetch = () => {
    controller.abort();
    };

    const resendFetch = () => {
    cancelFetch();
    fetchData();
    };

    const data = { result, error, status, loading };
    return [data, fetchData, cancelFetch, resendFetch];
    }