Skip to content

Cherrerotinoco/react-fetch-hook

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-fetch-hook

CircleCI npm version npm downloads

React hook for conveniently use Fetch API.

  • Tiny (556 B). Calculated by size-limit
  • Both Flow and TypeScript types included
import React from "react";
import useFetch from "react-fetch-hook";

const Component = () => {
  const { isLoading, data } = useFetch("https://swapi.co/api/people/1");

  return isLoading ? (
    <div>Loading...</div>
  ) : (
    <UserProfile {...data} />
  );
};

useFetch accepts the same arguments as fetch function.

Installation

Install it with yarn:

yarn add react-fetch-hook

Or with npm:

npm i react-fetch-hook --save

Usage

Custom formatter

Default is response => response.json() formatter. You can pass custom formatter:

const { isLoading, data } = useFetch("https://swapi.co/api/people/1", {
    formatter: (response) => response.text()
});

Error handling

The useFetch hook returns an error field at any fetch exception. The error field extends Error and has status and statusText fields equal to Response.

...

const Component = () => {
  const { isLoading, data, error } = useFetch("https://swapi.co/api/people/1");

  if (error) {
    return <div>
      <p>Code: ${error.status}</p>
      <p>Message: ${error.statusText}</p>
    </div>
  }

  ...
};

Abort request

The useFetch hook returns an abort() function that can be implemented whenever you need to cancel the request. You can pass custom option: {abortController: true} to use this funcionality. abort implements the Abort Controller Interface AbortController. You can see it in codesandbox-> Code

...

const Component = () => {

  const defaultUrl = "https://swapi.dev/api/people/1";
  const [url, useUrl] = useState(defaultUrl);
  const [fetchUrl, useFetchUrl] = useState(defaultUrl);


 const { isLoading, data, abort } = useFetch(fetchUrl, {
    abortController: true,
  });

  const handleOnClick = (event) => {
    event.preventDefault();
    console.log("Fetching...");
    useFetchUrl(url);
  };

  return (
    <div>
      <input
        id="url"
        type="text"
        name="url"
        onChange={(event) => useUrl(event.target.value)}
        placeholder={"Url to fetch"}
        value={url}
      />
      <button onClick={handleOnClick}>Fecth Url</button>
      <button onClick={() => abort()}>Abort</button>
      <p>isLoading: {(isLoading && "true") || "false"}</p>
      <p>Name: {data && data.name}</p>
    </div>
  );



};
...

Multiple requests

Multiple useFetch in the same file/component supported:

const result1 = useFetch("https://swapi.co/api/people/1");
const result2 = useFetch("https://swapi.co/api/people/2");

if (result1.isLoading && result2.isLoading) {
  return <div>Loading...</div>;
}

return <div>
    <UserProfile {...result1.data} />
    <UserProfile {...result2.data} />
</div>

Depends

The request will not be called until all elements of depends array be truthy. Example:

const {authToken} = useContext(authTokenContext);
const [someState, setSomeState] = useState(false);
const { isLoading, data } = useFetch("https://swapi.co/api/people/1", {
    depends: [!!authToken, someState] // don't call request, if haven't authToken OR someState: false
});

See example.

Re-call requests

If any element of depends changed, request will be re-call. For example, you can use react-use-trigger for re-call the request:

import createTrigger from "react-use-trigger";
import useTrigger from "react-use-trigger/useTrigger";

const requestTrigger = createTrigger();

export const Subscriber = () => {
    const requestTriggerValue = useTrigger(requestTrigger);

    const { isLoading, data } = useFetch("https://swapi.co/api/people/1", {
        depends: [requestTriggerValue]
    });

    return <div />;
}

export const Sender = () => {
    return <button onClick={() => {
        requestTrigger() // re-call request
    }}>Send</button>
}

usePromise

For custom promised function.

import React from "react";
import usePromise from "react-fetch-hook/usePromise";
import callPromise from "..."

const Component = () => {
  const { isLoading, data } = usePromise(() => callPromise(...params), [...params]);

  return isLoading ? (
    <div>Loading...</div>
  ) : (
    <UserProfile {...data} />
  );
};
  • Basic - Just fetch data with useFetch.
  • Depends - Usage depends option for refresh query.
  • Pagination - Usage usePaginationRequest for infinite scroll implementation.
  • Abort - Usage abortController:true for aborting promises .

API

useFetch

Create a hook wrapper for fetch call.

useFetch(
    path: RequestInfo,
    options?: {
        ...RequestOptions,
        formatter?: Response => Promise
        depends?: Array<boolean>
        abortController: Boolean
    },
    specialOptions?: {
        formatter?: Response => Promise
        depends?: Array<boolean>
    }
): TUseFetchResult

where TUseFetchResult is:

{
    data: any,
    isLoading: boolean,
    error: any
    abort: any,
}

RequestInfo, RequestOptions is fetch args.

usePromise

usePromise<T, I: $ReadOnlyArray<mixed>>(
    callFunction: ?(...args: I) => Promise<T>,
    ...inputs: I
): TUsePromiseResult<T>

where TUsePromiseResult<T> is

type TUsePromiseResult<T> = {
    data: ?T,
    isLoading: boolean,
    error: mixed
    abort: mixed
}

Experimental: usePaginatedRequest

⚠️ Warning: this method is experimental, API can be changed.

Create a paginated request.

usePaginatedRequest = <T>(
    request: (params: { limit: number, offset: number }) => Promise<Array<T>>,
    limit: number,
    ...depends: Array<any>
): {
    data: Array<T>,
    loadMore?: () => mixed,
    hasMore: boolean
};

Who Uses react-fetch-hook

Open Source projects

Companies

See more

About

React hook for conveniently use Fetch API

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%