{"id":13727331,"url":"https://github.com/dai-shi/react-suspense-fetch","last_synced_at":"2025-04-04T21:11:20.107Z","repository":{"id":36467933,"uuid":"226349481","full_name":"dai-shi/react-suspense-fetch","owner":"dai-shi","description":"[NOT MAINTAINED] A low-level library for React Suspense for Data Fetching","archived":false,"fork":false,"pushed_at":"2023-05-17T10:27:01.000Z","size":2001,"stargazers_count":297,"open_issues_count":8,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-28T20:11:12.391Z","etag":null,"topics":["fetch","react","react-suspense","reactjs","rest-api"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dai-shi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-12-06T14:43:05.000Z","updated_at":"2025-02-11T15:51:02.000Z","dependencies_parsed_at":"2024-01-06T07:58:24.120Z","dependency_job_id":"ef0a94c8-7908-4907-aa4f-6fe011e9c6f8","html_url":"https://github.com/dai-shi/react-suspense-fetch","commit_stats":{"total_commits":98,"total_committers":6,"mean_commits":"16.333333333333332","dds":"0.15306122448979587","last_synced_commit":"120d6145b2ad925cd0a0d09a52da9d4193806c60"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Freact-suspense-fetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Freact-suspense-fetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Freact-suspense-fetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dai-shi%2Freact-suspense-fetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dai-shi","download_url":"https://codeload.github.com/dai-shi/react-suspense-fetch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247249532,"owners_count":20908212,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fetch","react","react-suspense","reactjs","rest-api"],"created_at":"2024-08-03T01:03:50.122Z","updated_at":"2025-04-04T21:11:20.081Z","avatar_url":"https://github.com/dai-shi.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"This project is no longer maintained.\nReact will soon introduce [the `use` hook](https://github.com/reactjs/rfcs/pull/229) and `cache`.\nThey cover what this project was trying to accomplish.\n\n---\n\n# react-suspense-fetch\n\n[![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)\n[![npm](https://img.shields.io/npm/v/react-suspense-fetch)](https://www.npmjs.com/package/react-suspense-fetch)\n[![size](https://img.shields.io/bundlephobia/minzip/react-suspense-fetch)](https://bundlephobia.com/result?p=react-suspense-fetch)\n[![discord](https://img.shields.io/discord/627656437971288081)](https://discord.gg/MrQdmzd)\n\nA low-level library for React Suspense for Data Fetching\n\n## Introduction\n\nReact 18 comes with Suspense (sort of),\nbut Suspense for Data Fetching is left for data frameworks.\nThe goal of this library is to provide a thin API\nto allow Suspense For Data Fetching without richer frameworks.\n\nProject status: Waiting more feedbacks before finalizing the API.\n\n## Install\n\n```bash\nnpm install react-suspense-fetch\n```\n\n## Usage\n\n```javascript\nimport React, { Suspense, useState, useTransition } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport { createFetchStore } from 'react-suspense-fetch';\n\n// 1️⃣\n// Create a store with an async function.\n// The async function can take one input argument.\n// The input value becomes the \"key\" of cache.\n// By default, keys are compared with strict equal `===`.\nconst store = createFetchStore(async (userId) =\u003e {\n  const res = await fetch(`https://reqres.in/api/users/${userId}?delay=3`);\n  const data = await res.json();\n  return data;\n});\n\n// 2️⃣\n// Prefetch data for the initial data.\n// We should prefetch data before getting the result.\n// In this example, it's done at module level, which might not be ideal.\n// Some initialization function would be a good place.\n// We could do it in render function of a component close to root in the tree.\nstore.prefetch('1');\n\n// 3️⃣\n// When updating, wrap with startTransition to lower the priority.\nconst DisplayData = ({ result, update }) =\u003e {\n  const [isPending, startTransition] = useTransition();\n  const onClick = () =\u003e {\n    startTransition(() =\u003e {\n      update('2');\n    });\n  };\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003eFirst Name: {result.data.first_name}\u003c/div\u003e\n      \u003cbutton type=\"button\" onClick={onClick}\u003eRefetch user 2\u003c/button\u003e\n      {isPending \u0026\u0026 'Pending...'}\n    \u003c/div\u003e\n  );\n};\n\n// 4️⃣\n// We should prefetch new data in an event handler.\nconst Main = () =\u003e {\n  const [id, setId] = useState('1');\n  const result = store.get(id);\n  const update = (nextId) =\u003e {\n    store.prefetch(nextId);\n    setId(nextId);\n  };\n  return \u003cDisplayData result={result} update={update} /\u003e;\n};\n\n// 5️⃣\n// Suspense boundary is required somewhere in the tree.\n// We can have many Suspense components at different levels.\nconst App = () =\u003e (\n  \u003cSuspense fallback={\u003cspan\u003eLoading...\u003c/span\u003e}\u003e\n    \u003cMain /\u003e\n  \u003c/Suspense\u003e\n);\n\ncreateRoot(document.getElementById('app')).render(\u003cApp /\u003e);\n```\n\n## API\n\n\u003c!-- Generated by documentation.js. Update this documentation by updating the source code. --\u003e\n\n### FetchStore\n\nfetch store\n\n`prefetch` will start fetching.\n`get` will return a result or throw a promise when a result is not ready.\n`preset` will set a result without fetching.\n`evict` will remove a result.\n`abort` will cancel fetching.\n\nThere are three cache types:\n\n*   WeakMap: `input` has to be an object in this case\n*   Map: you need to call evict to remove from cache\n*   Map with areEqual: you can specify a custom comparator\n\nType: {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}\n\n#### Properties\n\n*   `prefetch` **function (input: Input): void** \n*   `get` **function (input: Input, option: GetOptions): Result** \n*   `preset` **function (input: Input, result: Result): void** \n*   `evict` **function (input: Input): void** \n*   `abort` **function (input: Input): void** \n\n### createFetchStore\n\ncreate fetch store\n\n#### Parameters\n\n*   `fetchFunc` **FetchFunc\\\u003cResult, Input\u003e** \n*   `cacheType` **CacheType\\\u003cInput\u003e?** \n*   `presets` **Iterable\\\u003cany\u003e?** \n\n#### Examples\n\n```javascript\nimport { createFetchStore } from 'react-suspense-fetch';\n\nconst fetchFunc = async (userId) =\u003e (await fetch(`https://reqres.in/api/users/${userId}?delay=3`)).json();\nconst store = createFetchStore(fetchFunc);\nstore.prefetch('1');\n```\n\n## Examples\n\nThe [examples](examples) folder contains working examples.\nYou can run one of them with\n\n```bash\nPORT=8080 npm run examples:01_minimal\n```\n\nand open \u003chttp://localhost:8080\u003e in your web browser.\n\nYou can also try them in codesandbox.io:\n[01](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/01\\_minimal)\n[02](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/02\\_typescript)\n[03](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/03\\_props)\n[04](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/04\\_auth)\n[05](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/05\\_todolist)\n[06](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/06\\_reactlazy)\n[07](https://codesandbox.io/s/github/dai-shi/react-suspense-fetch/tree/main/examples/07\\_wasm)\n\n## Blogs\n\n*   [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/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdai-shi%2Freact-suspense-fetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdai-shi%2Freact-suspense-fetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdai-shi%2Freact-suspense-fetch/lists"}