A Fetch Library Support React New Suspense SSR

Related tags

use-suspense-fetch
Overview

use-suspense-fetch

A data fetching library for React Suspense. inspired by use-asset

Feature

Install

yarn add use-suspense-fetch or npm install use-suspense-fetch

Use

use react 18 createRoot

new Promise(resolve => { setTimeout(() => resolve(fakeData), 2000) }) ) return (
    {res.map(r => (
  • {r}
  • ))}
) } function App() { return (
) } const root = createRoot(document.getElementById('root')) root.render( ) ">
const fakeData = [
  "Wait, it doesn't wait for React to load?",
  'How does this even work?',
  'I like marshmallows'
]

import suspenseFetch from 'use-suspense-fetch'
import { createRoot } from 'react-dom'
import { Suspense } from 'react'

export default function Comment() {
  const res = suspenseFetch(
    'fakeData',
    () =>
      new Promise(resolve => {
        setTimeout(() => resolve(fakeData), 2000)
      })
  )

  return (
    <ul>
      {res.map(r => (
        <li>{r}</li>
      ))}
    </ul>
  )
}

function App() {
  return (
    <div>
      <Suspense>
        <Comment />
      </Suspense>
    </div>
  )
}

const root = createRoot(document.getElementById('root'))

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

suspenseFetch will use globalCache

SSR

  1. use SuspenseFetchProvider in server and client

server in fixtures/ssr/server/render.js line 43

import * as React from 'react'
// import {renderToString} from 'react-dom/server';
import { pipeToNodeWritable } from 'react-dom/server'
import App from '../src/App'
import { DataProvider } from '../src/data'
import { API_DELAY, ABORT_DELAY } from './delays'
import { SuspenseFetchProvider, renderScriptHtml } from 'use-suspense-fetch'

...etc

// get some method includes getCache
const method = createSuspenseFetch()

const { startWriting, abort } = pipeToNodeWritable(
    <DataProvider data={data}>
      <SuspenseFetchProvider method={method}>
        <App assets={assets} />
      </SuspenseFetchProvider>
    </DataProvider>,
    res,
    {
      onReadyToStream() {
        // If something errored before we started streaming, we set the error code appropriately.
        res.statusCode = didError ? 500 : 200
        res.setHeader('Content-type', 'text/html')
        res.write('')
        startWriting()
      },
      onError(x) {
        didError = true
        console.error(x)
      },
      onCompleteAll() {
        // in onCompleteAll get all resolved suspense data
        const cache = method.getCache()
        // render cache to htmlStr
        const str = renderScriptHtml(cache)
        // return str
        res.write(str)
        console.log(str)
        console.log('------- complete ---------')
      }
    }
  )

client in fixtures/ssr/src/index.js line 15

import { hydrateRoot } from 'react-dom'
import App from './App'
import { SuspenseFetchProvider, getServerInitialData } from 'use-suspense-fetch'

// get cached initialData
const initialData = getServerInitialData()

console.log('initialData:', initialData)

hydrateRoot(
  document,
  // use cache initialData, in order to avoid fetch data again in client.
  <SuspenseFetchProvider initialData={initialData}>
    <App assets={window.assetManifest} />
  </SuspenseFetchProvider>
)
  1. use useFetch in Component

in fixtures/ssr/src/Comments2.js

new Promise(resolve => setTimeout(() => { resolve(fakeData) }, API_DELAY) ) ) console.log('post:', response) return (
    {response.map((post, i) => (
  • {post}
  • ))}
) } ">
import { useFetch } from 'use-suspense-fetch'

const API_DELAY = 2000
const fakeData = [
  "Wait, it doesn't wait for React to load?",
  'How does this even work?',
  'I like marshmallows'
]

export default function Comments2({ subreddit }) {
  // if server cache has data, useFetch will use it directly, not to fetch data again.
  const response = useFetch(
    subreddit,
    () =>
      new Promise(resolve =>
        setTimeout(() => {
          resolve(fakeData)
        }, API_DELAY)
      )
  )

  console.log('post:', response)
  return (
    <ul>
      {response.map((post, i) => (
        <li key={i}>{post}</li>
      ))}
    </ul>
  )
}

Api

interface SuspenseProviderProps {
  children?: React.ReactNode
  // LRU Option
  options?: Options<string, any>
  // if method exist, it will use method, else suspenseProvider will create cache in component.
  // you can use it in server. example => fixtures/ssr/server/render.js
  method?: ReturnMethod<Response>
  // get server resolved suspense data, you can use it in client. example => fixtures/ssr/src/index.js
  initialData?: Record<string, Response>
}
  • useSuspenseFetch: you can use it in Component that is inside the Suspense. It will return
    • fetch(key: string, fn: () => Promise): get data from server
    • refresh(key?: string): clear cache
    • peek(key: string): get [key] data
    • preload(key: string, fn: () => Promise): get data early
    • getCache(): get all cache data
  • useFetch(key: string, fn: () => Promise): get data from server. It is equal to fetch.
  • renderScriptHtml(cache: LRU): render script html string, use it in server.
  • getServerInitialData(key?: string): get server cache suspense data, if key not exist it will use default key. only use it in client.

if you use useSuspenseFetch or useFetch, you have to use SuspenseProvider in the top of component.

you can also use the api below, they use global cache and don't depend on SuspenseProvider.

  • suspenseFetch: it it equal useFetch, you can import suspenseFetch from 'use-suspense-fetch'
  • refresh(key?: string): clear cache, you can import { refresh } from 'use-suspense-fetch'
  • peek(key: string): get [key] data, you can import { peek } from 'use-suspense-fetch'
  • preload(key: string, fn: () => Promise): use it to get data early, you can import { preload } from 'use-suspense-fetch'
Issues
Releases(1.5.0)
Owner
Snake
can't sing, dance, rap, but can code, 🏀
Snake
The next generation state management library for React

The next generation state management library for React

Bytedance Inc. 150 Sep 18, 2021
CSS media queries for React

react-media react-media is a CSS media query component for React. A <Media> component listens for matches to a CSS media query and renders stuff based

React Training 2.4k Oct 15, 2021
📦 noov.js for react ssr solution

?? noov.js for react ssr solution

art-design 17 Jul 13, 2021
Declarative hotkey and focus area management for React

React HotKeys A declarative library for handling hotkeys and focus areas in React applications. Upgrading from 1.*.* ? See the upgrade notes. Looking

Aleck Greenham 1.9k Oct 3, 2021
React-Godfather aims to explore an alternative mental model for function components.

React-Godfather "Look ma, no Hooks!" React-Godfather aims to explore an alternative mental model for function components. It adds a thin layer between

John Kapolos 17 Sep 20, 2021
A lightweight react library that converts raw HTML to a React DOM structure.

A lightweight react library that converts raw HTML to a React DOM structure.

Arve Knudsen 652 Oct 17, 2021
Cookie cutter react portfolio suited perfectly for Github Pages

Cookie cutter react portfolio suited perfectly for Github Pages, get up and running in less then 5 minutes, just edit the data.json file and off you go!

null 37 Sep 9, 2021
A component for React that utilizes the Counterpart module to provide multi-lingual/localized text content.

React Translate Component Translate is a component for React that utilizes the Counterpart module and the Interpolate component to provide multi-lingu

Martin Andert 325 Apr 14, 2021
iOS Today Widget in React Native

React Native Today Widget Experimental library investigating limits of implementation iOS App Extensions using React Native. Sample result from Comple

Matěj Kříž 343 Oct 3, 2021
A ReactJS password recovery box component built using the FluentUI library

A ReactJS password recovery box component built using the FluentUI library

Boia Alexandru 2 Sep 20, 2021
A static site generator powered by Deno + React

A static site generator powered by Deno + React

xcatliu 1.2k Oct 18, 2021
A simple Facebook Chat Head like bubble for react native

react-native-floating-bubble A simple Facebook Chat Head like bubble for react native. Special thanks to bubble-for-android because this is just react

null 109 Oct 14, 2021
React-Native library for the WidgetKit framework. Integrate a Widget into your App 🍏📱

react-native-widgetkit React-Native Library for the iOS ?? WidgetKit framework Table of Contents ?? Introduction ??‍?? Installation ??‍ Usage ????‍??

Fasky 82 Oct 13, 2021
Extended utils for ⚛️ React.Children data structure that adds recursive filter, map and more methods to iterate nested children.

React Children Utilities Recursive and extended utils for React children opaque data structure. Installation Available as a package and can be added t

Fernando Pasik 183 Oct 5, 2021
Collection of Google fonts as typeface data for usage with three.js, react-three-fiber, and other tools.

Collection of Google fonts as typeface data for usage with three.js, react-three-fiber, and other tools.

Components AI 44 Oct 3, 2021
React Refresh Token with JWT and Axios Interceptors example

Buid React JWT Refresh Token example with Axios Interceptors - Refresh Token in React.js, Axios silent refresh JWT token example

null 18 Sep 30, 2021
🤖 React Native Android widgets bridged to JS, a proof of concept

React Native Android Widget Proof Of Concept ?? Using React Native and having Android widgets is possible. Create buttons in Java / Android XML to tri

Netbeast 186 Sep 21, 2021
Because your state management code should be domain-agnostic.

Because your state management code should be domain-agnostic.

Zachary DeRose 3 Oct 6, 2021
A QRCode component for use with React.

qrcode.react A React component to generate QR codes. Installation npm install qrcode.react Usage var React = require('react'); var QRCode = require('q

Paul O’Shannessy 2.6k Oct 15, 2021