Why use Suspense in React Server Components

203 Views Asked by At

I feel like there is a gap in my understanding around SSR / SSG and <Suspense /> in React Server components, in the context of Next.js /app router.

Question: why would I ever use <Suspense /> in a React server component?

Situation: say I have a React server component /app/page.tsx:

import apiRoute from './constants/apiRoute'
import { DisplayData } from './components/DisplayData'

export default async function Home() {
  const resp = await fetch(apiRoute as string)
  const data = await resp.json()

  return (
    <main>
      <h1>My Site</h1>
      <DisplayData data={data} />
    </main>
  )
}

So my understanding is that this function is run on a server (Node.js). The server makes a request to apiRoute and then uses the data returned to generate a static HTML document (SSG). This HTML document (static asset) is then served by my application at /. ie a client that makes a request to http://<mydomain.com>/ will download this HTML file. (And then perhaps a <script /> tag will load a JS script from the Node.js server and hydrate the page/application in a subsequent request.)

Now if instead I did:

const resp = await fetch(apiRoute as string, {
  cache: 'no-cache',
})

The situation would be identical except that a fresh static HTML file would be created on the Node.js server each and every time a client makes a request to http://<mydomain.com>/ and that HTML file would be served to the client. ie if the data at apiRoute changed between client requests that updated data would be reflected in the static HTML document served to the client. As I understand it this is SSR.

But I often see people online doing stuff like this:

import { Suspense } from 'react'

export default async function Home() {
  const resp = await fetch(apiRoute as string)
  const data = await resp.json()

  return (
    <main>
      <h1>My Site</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <DisplayData data={data} />
      </Suspense>
    </main>
  )
}

I don't understand why. To me it seems like the whole point is the HTML is created on the server before it is sent to the client and in that static HTML there is content that was populated (via React templating) by the data but the asset served and downloaded is now just static HTML (ie pretty much just text).

There should never be a "Loading" state. The client gets the whole static HTML file at once and the data is already in it. I could see why this would make sense in the context of a 'use client' component that uses JS to fetch data and while that HTTP request cycle is pending completion, it would show a loading state. But I am not understanding what is happening here with <Suspense /> fallbacks in server components. This Loading... state should never be shown. As soon as the client gets the HTML document, it's already got the data because the Node.js server had the data before it could finish creating the file that was to be served to the client; in both the SSR and SSG situations.

What am I missing here? What is the proper role of <Suspense /> in React server components? What advantages does it provide to me as the developer and to my application? I feel like I haven't found a use case for <Suspense /> in React server components, am I making my life harder?

0

There are 0 best solutions below