react-suspense-fetch

A primitive library for React Suspense Render-as-You-Fetch

Usage no npm install needed!

<script type="module">
  import reactSuspenseFetch from 'https://cdn.skypack.dev/react-suspense-fetch';
</script>

README

react-suspense-fetch

CI npm size discord

A primitive library for React Suspense Render-as-You-Fetch

Introduction

The new Render-as-You-Fetch pattern is mind-blowing. So far, only Relay implemented that pattern for GraphQL. This library aims at implementing that pattern for REST APIs.

This is an experimental library. Here's the list of design decisions:

  • No React Hooks interface
  • No global cache
  • Primitive API for libraries

Install

npm install react-suspense-fetch

Usage

import React, { Suspense, useState, unstable_useTransition as useTransition } from 'react';
import ReactDOM from 'react-dom';

import { createFetchStore } from 'react-suspense-fetch';

const DisplayData = ({ result, update }) => {
  const [startTransition, isPending] = useTransition();
  const onClick = () => {
    startTransition(() => {
      update('2');
    });
  };
  return (
    <div>
      <div>First Name: {result.data.first_name}</div>
      <button type="button" onClick={onClick}>Refetch user 2</button>
      {isPending && 'Pending...'}
    </div>
  );
};

const fetchFunc = async userId => (await fetch(`https://reqres.in/api/users/${userId}?delay=3`)).json();
const store = createFetchStore(fetchFunc);
store.prefetch('1');

const Main = () => {
  const [id, setId] = useState('1');
  const result = store.get(id);
  const update = (nextId) => {
    store.prefetch(nextId);
    setId(nextId);
  };
  return <DisplayData result={result} update={update} />;
};

const App = () => (
  <Suspense fallback={<span>Loading...</span>}>
    <Main />
  </Suspense>
);

ReactDOM.unstable_createRoot(document.getElementById('app')).render(<App />);

API

FetchStore

fetch store

get will throw a promise when a result is not ready. prefetch will start fetching. evict will remove a result. If input is an object, a result will be stored in WeakMap. Othrewise, a result will be stored in Map.

Type: {get: function (input: Input): Result, prefetch: function (input: Input): void, evict: function (input: Input): void}

Properties

  • get function (input: Input): Result
  • prefetch function (input: Input): void
  • evict function (input: Input): void

createFetchStore

create fetch store

Parameters

  • fetchFunc FetchFunc<Result, Input>
  • cacheType ({type: "WeakMap"} | {type: "Map", areEqual: function (a: Input, b: Input): boolean?})?
  • preloaded Iterable<any>?

Examples

import { createFetchStore } from 'react-suspense-fetch';

const fetchFunc = async (userId) => (await fetch(`https://reqres.in/api/users/${userId}?delay=3`)).json();
const store = createFetchStore(fetchFunc);
store.prefetch('1');

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 npm run examples:01_minimal

and open http://localhost:8080 in your web browser.

You can also try them in codesandbox.io: 01 02 03 04 05 06 07

Blogs