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

use-suspense-fetch

v1.7.0

Published

A data fetching library for React Suspense. inspired by [use-asset](https://github.com/pmndrs/use-asset)

Downloads

539

Readme

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

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('<!DOCTYPE html>')
        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

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'