question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Avoiding waterfalls with Suspense

See original GitHub issue

Side note: I am writing this with my jaw on the floor. What a clean API. Nice work guys. 😍

This issue refers to the idea of waterfalls as mentioned in the react docs. https://reactjs.org/docs/concurrent-mode-suspense.html#for-library-authors

From a glance, it appears that the suspense based API does not take the above optimization into consideration. If I am not mistaken, to avoid waterfalls, we need to declare the API calls first(which will init the fetch calls), and then read the data from another call (read method in relay), which will throw the promise.

Is this already done in the library? If not, do you guys plan to do it in the future? How would the API look like?


PS: In my head, the API should look something like below

function MyComponent(props) {
    // First we declare the list of fetch calls. Here we use an object. Could be an array instead.
    // Doing this will NOT trigger suspense. i.e. A promise shall not be thrown.
    // But the API calls will be triggered in parallel  
    const fetcher = useSuspenseSwr({
         key1: {/*fetch config for key 1*/},
         key2: {/*fetch config for key 2*/},
    });

    // and then call fetcher.fetch('key1') somewhere in the code
    // This is when the promise will be thrown
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:8
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
yoshiko-pgcommented, Jul 2, 2020

I’m working on my own project to simply avoid the waterfalls in this way. If it helps.

// Component.tsx
import { useSWR } from './WrappedSwr'

export const Component = () => {
  const resource1 = useSWR<YourResponseType1>('/path1', fetcher) // fetch1
  const resource2 = useSWR<YourResponseType2>('/path2', fetcher) // fetch2
  const data1 = resource1.read() // throw proimse
  const data2 = resource2.read() // throw proimse

  // or you can pass the resource to a child component

  // return (
  //   <Suspense>
  //     <Child resource={resource1} />  // props.resource.read() in Child Component
  //   </Suspense>
  // )

  // ...
// WrappedSwr.ts
import useRawSWR, { mutate, responseInterface } from 'swr'

const useSWR = <Data>(
  key: string,
  fetcher: (args: any) => Data | Promise<Data>,
): Resource<Data> => {
  try {
    const res = useRawSWR<Data>(key, fetcher)
    // If the data is in swr's cache
    return { read: () => res.data as Data }
  } catch (promiseOrError) {
    if (typeof promiseOrError.then === 'function') {
      return wrapPromise<responseInterface<Data, Error>>(promiseOrError)
    }
    throw promiseOrError
  }
}

// from: https://codesandbox.io/s/frosty-hermann-bztrp?file=/src/fakeApi.js
function wrapPromise<T extends { data?: any }>(promise: Promise<T>) {
  let status: 'success' | 'pending' | 'error' = 'pending'
  let result: T | Error
  const suspender = promise.then(
    (r) => {
      status = 'success'
      result = r
    },
    (e) => {
      status = 'error'
      result = e
    },
  )
  return {
    read() {
      if (status === 'pending') {
        throw suspender
      } else if (status === 'error') {
        throw result
      } else if (status === 'success') {
        return (result as T).data
      }
      throw new Error('unknown status in wrapPromise')
    },
  }
}

export { useSWR, mutate }
0reactions
miketamiscommented, Jun 23, 2022
Read more comments on GitHub >

github_iconTop Results From Across the Web

Avoiding waterfalls with Suspense · Issue #5 · vercel/swr
I'm working on my own project to simply avoid the waterfalls in this way. If it helps. // Component.tsx import { useSWR }...
Read more >
Suspense for Data Fetching (Experimental) - React
Libraries can prevent waterfalls by offering a more centralized way to do data fetching. For example, Relay solves this problem by moving the...
Read more >
React Suspense makes network waterfall when a component ...
I know that Suspense catches a Promise and shows Loading fallback until it is settled. So I understand why it make waterfall. Then,...
Read more >
Suspense for Data Fetching (Experimental) - chan.dev
Over time, Suspense will be React's primary way to read asynchronous data ... Prefer APIs that favor or enforce fetching before render —...
Read more >
React Suspense in Practice | CSS-Tricks
Has your brain turned to mush reading other things on Suspense that talked about waterfalls, fetch-on-render, preloading, etc? Don't worry about ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found