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-fast-fetch

v1.8.0

Published

Fetch and cache remote data in React apps

Downloads

261

Readme

React Fast Fetch

React Fast Fetch is a stale-while-revalidate implementation. It can fetch and cache remote data in React apps. Make your app load faster without writting more code. Try this demo

Get started

npm install --save react-fast-fetch
import axios from 'axios';
import { FetchConfigProvider, IndexedDBStore, useFetch } from 'react-fast-fetch';

const fetcher = (url) => axios.get(url).then((res) => res.data);

const store = new IndexedDBStore({ limit: 10000 });

function App() {
  const { data, loading, reload, error } = useFetch('/posts', {
    params: {
      keyword: 'hello',
      page: 1,
      pageSize: 10,
    },
  });

  return (
    <div>
      {loading && <span>Loading...</span>}
      {error && (
        <span>
          Failed to fetch data <button onClick={reload}>Reload</button>
        </span>
      )}
      {data?.map((post) => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}

render(
  <FetchConfigProvider fetcher={fetcher} store={store}>
    <App />
  </FetchConfigProvider>,
);

Choose a store

react-fast-fetch supports 4 types of storage:

| Store | Technology | Persistence | Limit of size | I/O Speed | | ----------------------------- | -------------- | ----------- | ----------------- | ------------ | | MemoryStore | a Map object | ❌ | your RAM capacity | < 1ms | | StorageStore (localStorage) | localStorage | ✅ | 5MB 😢 | < 1ms | | StorageStore (sessionStorage) | sessionStorage | ❌ | 5MB 😢 | < 1ms | | IndexedDBStore | IndexedDB | ✅ | your SSD capacity | 10~1000ms 😢 |

  • If you want to persist your data and share between tabs:
    • For large site with many APIs and huge amount of data, use IndexedDBStore
    • For small site with only a few APIs, use StorageStore (localStorage)
  • If you want to persist data between page refreshing and avoid sharing data between tabs, use StorageStore (sessionStorage)
  • If you don't want to persist your data, use MemoryStore

You can also use multiple different store in the same app, if you know what you really need!

MemoryStore

import { MemoryStore } from 'react-fast-fetch';

export const store = new MemoryStore({
  // maximum 2000 url to cache
  limit: 2000,
});

StorageStore

import { StorageStore } from 'react-fast-fetch';

export const store = new StorageStore({
  // or sessionStorage as you want
  storage: localStorage,
  // maximum 500 url to cache
  limit: 500,
});

IndexedDBStore

import { IndexedDBStore } from 'react-fast-fetch';

export const store = new IndexedDBStore({
  // database name
  dbName: 'my-store',
  // maximum 5000 url to cache
  limit: 5000,
});

Write a fetcher

fetch

const fetcher = (url) => fetch(url).then((res) => res.json());

axios

import axios from 'axios';

const fetcher = (url) => axios.get(url).then((res) => res.data);

useFetch hook

Fetch component

If you are writting React function components, <Fetch/> component is made for you:

import { useFetch } from 'react-fast-fetch';

class Posts extends React.Component {
  state = {
    posts: null,
  };

  render() {
    const { data, loading, reload, error } = this.state.posts || {};
    return (
      <div>
        <Fetch url="/posts?query=hello" onChange={(result) => this.setState({ posts: result })} />
        {loading && <span>Loading...</span>}
        {error && (
          <span>
            Failed to fetch data <button onClick={reload}>Reload</button>
          </span>
        )}
        {data?.map((post) => (
          <div key={post.id}>{post.title}</div>
        ))}
      </div>
    );
  }
}

Config

Here are two ways to configure react-fast-fetch.

// Use global config, recommended
<FetchConfigProvider fetcher={fetcher} store={store}>
  ...
</FetchConfigProvider>;

// Use local config, for flexibility
const { data } = useFetch('/url', { fetcher: customFetcher, store: customStore });

Both ways supports the following configuration:

Options

disabled

Disable data fetching. This is useful when some parameters is required to fetch data.

const [page, setPage] = useState(1);
const { data } = useFetch(`/posts?page=${page}`, { disabled: page < 1 });

interval

Auto-reload data in N milliseconds. Use it to keep data up-to-date.

const { data } = useFetch(`/notifications/unread`, { interval: 5000 });

onLoad

Callback when the intial load is done.

const [page, setPage] = useState(1);
const { data } = useFetch(`/posts?page=${page}`, {
  onLoad: (url, data) => {
    console.log(url, data);
  },
});

onReload

Callback when data is reloaded.

const [page, setPage] = useState(1);
const { data } = useFetch(`/posts?page=${page}`, {
  onReload: (url, data) => {
    console.log(url, data);
  },
});

Return

data

Result data returned by fetcher.

const { data } = useFetch('/posts/1');

loading

If here is NO cached data and fetcher is fetching data from remote, loading is set to true.

const { data, loading } = useFetch('/posts/1');
return (
  <div>
    {loading && <div>Loading...</div>}
    {data && <div>{data.title}</div>}
  </div>
);

reloading

If here is cached data and fetcher is fetching data from remote, reloading is set to true. In most cases, you don't need to notice user that it is reloading if the API is fast enough. If the API is indeed very slow, show some messages or progress bars that don't block user interaction.

const { data, loading } = useFetch('/posts/1');
return (
  <div>
    {loading && <div>Loading...</div>}
    {reloading && <div>Refreshing...</div>}
    {data && <div>{data.title}</div>}
  </div>
);

reload

A function to manually reload data from remote. Usually used in two cases:

  1. Automatic fetch failed. See error section bellow.
  2. You modified the resource. For example, you delete a post and then you need to reload the list.

error

Error throwed by fetcher. Usually mean user need to reload the data.

const { data, loading } = useFetch('/posts/1');
return (
  <div>
    {loading && <div>Loading...</div>}
    {error && (
      <span>
        Failed to fetch data <button onClick={reload}>Reload</button>
      </span>
    )}
    {data && <div>{data.title}</div>}
  </div>
);