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 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-cached-fetch

v1.4.0

Published

React hook for fetching data with cache functionality

Downloads

41

Readme

react-cached-fetch

A simple react hook for data fetching with cache. It serves the cached version while waiting for the data to be fetched and then updates the cache with the fetched result. It is great for grids, lists or any other page that loads data.

Features:

✅ 0 dependencies ✅ Unopinionated You can use it with any HTTP client ✅ Chained calls react-cached-fetch lets you easily fetch data that depends on data returned by other API calls ✅ Programmatic refresh You can trigger refreshes programmatically ✅ Silent refresh You can silently send a new GET request to your API and have your UI updated automatically when it gets fullfiled ✅ TypeScript ready This library if fully written in TypeScript and supports generic types. You can use it both with plain JavaScript or with TypeScript

Table of Contents

Installation

Simply run:

yarn add react-cached-fetch

or:

npm install react-cached-fetch

Usage

Since the hook uses Context API to store the cached data, you must first wrap your app component (or only the part of your app where you want the cache to be available) with CachedFetchProvider.

import React from "react";
import { CachedFetchProvider } from "react-cached-fetch";

const App = () => {
  return (
    <CachedFetchProvider>
      <div className="App"></div>
    </CachedFetchProvider>
  );
};

Then you can use the useCachedFetch hook in your components.

import React from "react";
import { useCachedFetch } from "react-cached-fetch";

const UserList = () => {
  const { data: users, isLoading, hasError, refresh } = useCachedFetch(
    "http://my-api/users"
  );

  if (hasError) return <div>There was an error loading the data</div>;

  return (
    <div>
      <div>
        {data ? (
          users.map((user, key) => <span key={key}>{user.Name}</span>)
        ) : (
          <span>There are no users on our database</span>
        )}
      </div>
      {isLoading && <span>Updating list...</span>}

      <button onClick={refresh}>Manually trigger refresh</button>
    </div>
  );
};

export default UserList;

API

CachedFetchProvider

The CachedFetchProvider must be used to wrap all components that will use useCachedFetch hook in order for them to access the cached data. It is tipically used to wrap the entire App component, but you could use it at any component tree level.

Properties

| Property | type | required | description | | ------------------ | ----------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | globalOptions? | object | no | Global options that will be passed with every call of useCachedFetch, explained below. | | persistence? | 'none', 'session', or 'local' | no | The persistence strategy you'd like to use to store the cached data. 'session' means browser's session storage, 'local' means browser's local storage and 'none' means that the data will only be stored in memory. Defaults to 'none'. | | persistencePrefix? | string | yes, if persistence is different than 'none'. | The prefix to be used in the session/local storage's key. Example: if you set persistencePrefix to '@MyApp', the cache key will be '@MyApp-react-cached-fetch'. An error will be thrown if you set persistence to 'local' or 'session' and fail to provide a persistencePrefix. It is made like this to avoid conflicts when using react-cached-fetch in multiple apps on the same development environment. |

useCachedFetch

The useCachedFetch hook can be used to serve cached data while it fetches new data from a specified endpoint. It will perform the fetching automatically once when the component who's calling it is rendered, and it is also possible to trigger other fetches programmatically by calling the refresh function returned from it. Whenever the fetcher function gets triggered, it saves the request result in a cache whose key is the provided endpoint, so this new data can be returned by the hook while it waits for an update whenever the component gets remounted.

Arguments

| Argument | type | required | description | | -------- | ------ | -------- | ------------------------------------------------------------------- | | route | string | yes | The enpoint to which the fetcher function will send the GET request. | | options? | object | no | Aditional options, explained below. |

Returned results

The return value of useCachedFetch is an object containing the following properties:

| Property | type | default | description | | --------- | -------- | --------- | ---------------------------------------------------------------------------------------- | | data | any | undefined | The remote data returned by the fetcher function. | | hasError | boolean | false | A boolean indicating if there was an error while fetching the data. | | isLoading | boolean | false | A boolean describing if the fetcher function is waiting for the request to be completed. | | refresh | function | | A function to manually trigger the fetcher function and update the cache. |

Options

The available options that may be passed to useCachedFetch are:

  • headers: an object containg the headers to be sent with the request. Defaults to {}.

  • fetcher: the fetcher function used to obtain the data. Defaults to

async (route: string, headers: IHeaderOptions): Promise<any> => {
  const response = await fetch(route, { headers });
  const result = await response.json();

  if (!response.ok) {
    throw new Error(
      result.message || response.statusText || 'Request failed.',
    );
  }

  return result;
}
  • initialValue: the initial value for the data property returned by useCachedFetch. Defaults to undefined.

  • dependencies: an array with dependencies on which the fetcher function depends on to be triggered. The array must only contain boolean values. The hook will wait until all values on the array are true before calling the fetcher function. It is useful in cases where you have to make sure of something before fetching the data, like veryfing an authentication token or chaining calls. Here is an example:

const UserInformationDashboard = () => {
  const { data: user } = useCachedFetch("users", {
    initialValue: {
      id: ''
    }
  });

  const { data: userDetails } = useCachedFetch(`userDetails/${user.id}`, {
    initialValue: {
      name: "",
      posts: 0
    },
    dependencies: [!!user.id]
  });

  return <>Your Code</>;
};

In the example above the request to userDetails/:id will only be made once the request to users has been fulfilled.

Global Options

It is also possible to globally provide all available options so that every call to useCachedFetch will use them. You can do so by passing the globalOptions property to CachedFetchProvider:

import React from "react";
import { CachedFetchProvider } from "react-cached-fetch";

import { useAuth } from './src/hooks/auth';

const App = () => {
  const { jwt } = useAuth() // Get a JWT to check if the user is authenticated

  return (
    <CachedFetchProvider
      globalOptions={{
        headers: {
          mode: "cors",
          authorization: `Bearer ${jwt}`
        },
        initialValue: []
      }}
    >
      <div className="App"></div>
    </CachedFetchProvider>
  );
};

Note that the options passed as argument to useCachedFetch will override the globalOptions. Therefore, if you use the globalOptions shown above and then make a call to useCachedFetch like this:

const { data } = useCachedFetch("http://my-api/lists", {
  initialValue: {}
});

The initialValue of data will be {} and the headers option defined as globalOptions will be kept.

Usage with other HTTP clients

By default, the hook uses the standard fetch API to request the data, but you can use any other client you want by passing your custom fetcher function:

import React from "react";
import axios from "axios";
import { useCachedFetch } from "react-cached-fetch";

const UserList = () => {
  const { data, isLoading, hasError, refresh } = useCachedFetch(
    "http://my-api/users",
    {
      fetcher: async (route, headers) => {
        const { data } = await axios.get(route, { headers });
        return data;
      }
    }
  );

  return <div></div>;
};

export default UserList;

Of course you could also pass your custom fetcher function as a global option, so it would be used everytime you call useCachedFetch. This is a great way to take advantage of axios' baseURL and default headers.

Usage with Typescript

You can preset the type of the data you are fetching by passing it's type to useCachedFetch hook. Here is an example:

import React from "react";
import axios from 'axios';
import { useCachedFetch } from "react-cached-fetch";

interface IPost {
  id: string;
  title: string;
  content: string;
  likes: number;
};

const PostsList: React.FC = () => {
  const { data: posts, isLoading, hasError, refresh } = useCachedFetch<IPost[]>(
    "http://my-api/posts",
    {
      fetcher: async (route, headers) => {
        const { data } = await axios.get<IPost[]>(route, { headers });
        return data;
      },
      initialValue: []
    }
  );

  return <div></div>;
};

export default PostsList;

By doing this, you are typing your data as an array of posts. The type will also be extended to the fetcher function, that will have a return type of Promise<IPost[]> and to the initialValue option.

🤝 Contributing

Contributions, issues and feature requests are welcome. Feel free to check issues page if you want to contribute.

License

This project is MIT Licensed