stackademic

The leading education platform for anyone with an interest in software development.

React Suspense

Declaratively handle loading states for async rendering

Overview

Suspense lets a component "wait" for something before rendering, showing a fallback in the meantime. React catches the pending state thrown by a suspending child and renders the nearest <Suspense> boundary's fallback until the data or code is ready. It powers lazy code-splitting, streaming SSR, and data fetching in modern frameworks.

Syntax / Usage

Wrap suspending children in a boundary and provide a fallback.

import { Suspense, lazy } from 'react'

const Analytics = lazy(() => import('./Analytics'))

function Dashboard() {
  return (
    <Suspense fallback={<p>Loading analytics…</p>}>
      <Analytics />
    </Suspense>
  )
}

Examples

Data fetching with the use hook in a client component—use suspends until the promise resolves:

import { use, Suspense } from 'react'

function Profile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise)
  return <h1>{user.name}</h1>
}

function Page({ userPromise }: { userPromise: Promise<User> }) {
  return (
    <Suspense fallback={<Skeleton />}>
      <Profile userPromise={userPromise} />
    </Suspense>
  )
}

Nest boundaries so independent regions stream in separately and pair with an error boundary to catch rejected promises:

<ErrorBoundary fallback={<Error />}>
  <Suspense fallback={<Skeleton />}>
    <Feed />
    <Suspense fallback={<SidebarSkeleton />}>
      <Sidebar />
    </Suspense>
  </Suspense>
</ErrorBoundary>

Common Mistakes

  • Creating the promise inside the suspending component, so it re-fetches on every attempt
  • Forgetting an error boundary—rejected promises otherwise bubble uncaught
  • Expecting useEffect-based fetching to trigger Suspense; only suspense-enabled sources do
  • Wrapping too coarsely, so one slow region blocks unrelated content from showing
  • Using use conditionally—it follows the Rules of Hooks like other hooks

See Also

react-error-boundaries react-server-components use-effect