npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bjornagh/use-fetch

v0.0.12

Published

An easy-to-use React hook for doing fetch requests

Readme

@bjornagh/use-fetch

An easy-to-use React hook for doing fetch requests.

Features

  • 1️⃣ Dedupes requests done to the same endpoint. Only one request to the same endpoint will be initiated.
  • 💨 Caches responses to improve speed and reduce amount of requests.
  • 🛀 Automatically makes new requests if URL changes.
  • ⚛️ Small size, with only two dependencies: react and fetch-dedupe.

Install

npm install @bjornagh/use-fetch

# if yarn
yarn add @bjornagh/use-fetch

Usage

  1. Create a cache (new Map()) and render the FetchProvider at the top of your application.
import { FetchProvider } from "@bjornagh/use-fetch";

const cache = new Map();

ReactDOM.render(
  <FetchProvider cache={cache}>
    <App />
  </FetchProvider>,
  document.getElementById("container")
);
  1. Use useFetch in your component
import React from "react";
import { useFetch } from "@bjornagh/use-fetch";

function MyComponent() {
  const { data, fetching } = useFetch({
    url: "https://jsonplaceholder.typicode.com/todos"
  });

  return (
    <div>
      {fetching && "Loading..."}
      {data && data.map(x => <div key={x.id}>{x.title}</div>)}
    </div>
  );
}

See more examples in the examples section examples section .

API

useFetch accepts an object that supports the following properties

| Key | Default value | Description | |------|--------------|--------------| | url | | URL to send request to | | method | GET | HTTP method | | lazy | null | Lazy mode determines if a request should be done on mount and when the request parameters change (e.g. URL) or not. When null only GET requests are initiated when mounted and if for example the URL changes. If true this applies to all requests regardless of HTTP method. If false, requests are only initiated manually by calling doFetch, a function returned by useFetch| | init | {} | See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch init argument for which keys are supported | | dedupeOptions | {} | See https://github.com/jamesplease/fetch-dedupe#user-content-api dedupeOptions argument for which keys are supported | | cacheResponse | true if read request, false if write | Cache response or not | | requestKey | null | requestKey is used as cache key and to prevent duplicate requests. Generated automatically if nothing is passed. | | cachePolicy | null | Caching strategy | | refreshDoFetch | Function | By default doFetch method is memoized (by useCallback) by using the request (url+method+body). Use this to override if you get a stale doFetch. It receives one argument, the default request key. e.g. requestKey => requestKey + 'something' | | onError | Function | A callback function that is called anytime a fetch fails. Receives a Response as only argument. Logs to console by default | | onSuccess | Function | A callback function that is called anytime a fetch succeeds. Receives a fetch Response as only argument. Does nothing by default (noop) |

Return value

| Key | type | Description | |------|-------------|---------------| | response | Response | Response | | data | * | Request data response | | fetching | Boolean | Whether request is in-flight or not | | error | Response | Any errors from fetch | | requestKey | String | The key used as cache key and to prevent duplicate requests | | doFetch | Function | A function to initiate a request manually. Takes one argument: init, an object that is sent to fetch. See https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch (init argument for which keys are supported). Returns a promise. |

NOTE: Requests with Content-type set to application/json will automatically have their body stringified (JSON.stringify)

cachePolicy

  • cache-first - Uses response in cache if available. Makes request if not.
  • cache-and-network - Uses response in cache if available, but will also always make a new request in the background in order to refresh any stale data.
  • exact-cache-and-network - Similar to cache-and-network, but will only show cached response if the requests are identical (url+method+body).
  • network-only - Ignores cache and always makes a request.

Read requests (GET, OPTIONS, HEAD) default to cache-first.

Write requests (POST, DELETE, PUT, PATCH) default to network-only.

Examples

POST request and update view afterwards

function Demo() {
  // Fetch list of posts
  const posts = useFetch({
    url: "https://jsonplaceholder.typicode.com/posts"
  });

  // Prepare create request
  // This will not be initiated until you call `createPost.doFetch()`
  const createPost = useFetch({
    url: "https://jsonplaceholder.typicode.com/posts",
    method: "POST",
    init: {
      headers: {
        "Content-type": "application/json"
      }
    }
  });

  return (
    <div>
      <button
        onClick={() =>
          createPost
            .doFetch({
              body: {
                title: "foo",
                body: "bar",
                userId: 1
              }
            })
            .then(response => {
              if (response.ok) {
                // POST request was successful, refetch list of posts
                posts.doFetch();
              } else {
                // Do something with error response
              }
            })
        }
        disabled={createPost.fetching}
      >
        Create post
      </button>

      {!posts.data && posts.fetching && "Loading..."}
      {posts.data && posts.data.map(x => <h2 key={x.id}>{x.title}</h2>)}
    </div>
  );
}

Delay fetching using the lazy prop

Setting the lazy parameter to true tells useFetch to not start requesting on mount or when the request parameters change.

You can change this at any time. A common pattern where this feature is useful is when you want the user to apply some filters before you initiate a request.

Below is an example where a request is delayed until a search input contains at least two characters.

function LazyDemo() {
  const [searchFilter, setSearchFilter] = useState("");
  const posts = useFetch({
    url: `/posts?search=${searchFilter}`,
    lazy: searchFilter.length < 2 // Request is lazy as long as the input has less than two characters
  });

  return (
    <div>
      <input onChange={event => setSearchFilter(event.target.value)} />

      {posts.data && posts.data.map(x => <div key={x.id}>{x.title}</div>)}
    </div>
  );
}

How to set base URL, default headers and so on

Create your custom fetch hook. For example:

import { useFetch } from "@bjornagh/use-fetch";

function useCustomUseFetch({ url, init = {}, ...rest }) {
  // Prefix URL with API root
  const apiRoot = "https://my-api-url.com/";
  const finalUrl = `${apiRoot}${url}`;

  // Set a default header
  const finalHeaders = { ...init.headers };
  finalHeaders["Content-type"] = "application/json";

  // Ensure headers are sent to fetch
  init.headers = finalHeaders;

  return useFetch({ url: finalUrl, init, ...rest });
}

With a custom hook you could also set up a default error handler that show a toast message for example.

Credits

This library is heavily inspired by the excellent React library react-request