Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dai-shi/react-suspense-fetch

[NOT MAINTAINED] A low-level library for React Suspense for Data Fetching
https://github.com/dai-shi/react-suspense-fetch

fetch react react-suspense reactjs rest-api

Last synced: 2 days ago
JSON representation

[NOT MAINTAINED] A low-level library for React Suspense for Data Fetching

Awesome Lists containing this project

README

        

This project is no longer maintained.
React will soon introduce [the `use` hook](https://github.com/reactjs/rfcs/pull/229) and `cache`.
They cover what this project was trying to accomplish.

---

# react-suspense-fetch

[![CI](https://img.shields.io/github/actions/workflow/status/dai-shi/react-suspense-fetch/ci.yml?branch=main)](https://github.com/dai-shi/react-suspense-fetch/actions?query=workflow%3ACI)
[![npm](https://img.shields.io/npm/v/react-suspense-fetch)](https://www.npmjs.com/package/react-suspense-fetch)
[![size](https://img.shields.io/bundlephobia/minzip/react-suspense-fetch)](https://bundlephobia.com/result?p=react-suspense-fetch)
[![discord](https://img.shields.io/discord/627656437971288081)](https://discord.gg/MrQdmzd)

A low-level library for React Suspense for Data Fetching

## Introduction

React 18 comes with Suspense (sort of),
but Suspense for Data Fetching is left for data frameworks.
The goal of this library is to provide a thin API
to allow Suspense For Data Fetching without richer frameworks.

Project status: Waiting more feedbacks before finalizing the API.

## Install

```bash
npm install react-suspense-fetch
```

## Usage

```javascript
import React, { Suspense, useState, useTransition } from 'react';
import { createRoot } from 'react-dom/client';

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

// 1️⃣
// Create a store with an async function.
// The async function can take one input argument.
// The input value becomes the "key" of cache.
// By default, keys are compared with strict equal `===`.
const store = createFetchStore(async (userId) => {
const res = await fetch(`https://reqres.in/api/users/${userId}?delay=3`);
const data = await res.json();
return data;
});

// 2️⃣
// Prefetch data for the initial data.
// We should prefetch data before getting the result.
// In this example, it's done at module level, which might not be ideal.
// Some initialization function would be a good place.
// We could do it in render function of a component close to root in the tree.
store.prefetch('1');

// 3️⃣
// When updating, wrap with startTransition to lower the priority.
const DisplayData = ({ result, update }) => {
const [isPending, startTransition] = useTransition();
const onClick = () => {
startTransition(() => {
update('2');
});
};
return (


First Name: {result.data.first_name}

Refetch user 2
{isPending && 'Pending...'}

);
};

// 4️⃣
// We should prefetch new data in an event handler.
const Main = () => {
const [id, setId] = useState('1');
const result = store.get(id);
const update = (nextId) => {
store.prefetch(nextId);
setId(nextId);
};
return ;
};

// 5️⃣
// Suspense boundary is required somewhere in the tree.
// We can have many Suspense components at different levels.
const App = () => (
Loading...}>


);

createRoot(document.getElementById('app')).render();
```

## API

### FetchStore

fetch store

`prefetch` will start fetching.
`get` will return a result or throw a promise when a result is not ready.
`preset` will set a result without fetching.
`evict` will remove a result.
`abort` will cancel fetching.

There are three cache types:

* WeakMap: `input` has to be an object in this case
* Map: you need to call evict to remove from cache
* Map with areEqual: you can specify a custom comparator

Type: {prefetch: function (input: Input): void, get: function (input: Input, option: GetOptions): Result, preset: function (input: Input, result: Result): void, evict: function (input: Input): void, abort: function (input: Input): void}

#### Properties

* `prefetch` **function (input: Input): void**
* `get` **function (input: Input, option: GetOptions): Result**
* `preset` **function (input: Input, result: Result): void**
* `evict` **function (input: Input): void**
* `abort` **function (input: Input): void**

### createFetchStore

create fetch store

#### Parameters

* `fetchFunc` **FetchFunc\**
* `cacheType` **CacheType\?**
* `presets` **Iterable\?**

#### Examples

```javascript
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](examples) folder contains working examples.
You can run one of them with

```bash
PORT=8080 npm run examples:01_minimal
```

and open in your web browser.

You can also try them in codesandbox.io:
[01](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/01\_minimal)
[02](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/02\_typescript)
[03](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/03\_props)
[04](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/04\_auth)
[05](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/05\_todolist)
[06](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/06\_reactlazy)
[07](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/07\_wasm)

## Blogs

* [Diving Into React Suspense Render-as-You-Fetch for REST APIs](https://blog.axlight.com/posts/diving-into-react-suspense-render-as-you-fetch-for-rest-apis/)