知识库首页 知识库-世界 async-suspense-boundaries.md

async suspense boundaries

本地来源:Knowledge/World/项目/Practice/Claude-Skills/vercel-react-best-practices/rules/async-suspense-boundaries.md


title: Strategic Suspense Boundaries impact: HIGH impactDescription: faster initial paint tags: async, suspense, streaming, layout-shift


Strategic Suspense Boundaries

Instead of awaiting data in async components before returning JSX, use Suspense boundaries to show the wrapper UI faster while data loads.

Incorrect (wrapper blocked by data fetching):

async function Page() {
  const data = await fetchData() // Blocks entire page

  return (
    <div>
      <div>Sidebar</div>
      <div>Header</div>
      <div>
        <DataDisplay data={data} />
      </div>
      <div>Footer</div>
    </div>
  )
}

The entire layout waits for data even though only the middle section needs it.

Correct (wrapper shows immediately, data streams in):

function Page() {
  return (
    <div>
      <div>Sidebar</div>
      <div>Header</div>
      <div>
        <Suspense fallback={<Skeleton />}>
          <DataDisplay />
        </Suspense>
      </div>
      <div>Footer</div>
    </div>
  )
}

async function DataDisplay() {
  const data = await fetchData() // Only blocks this component
  return <div>{data.content}</div>
}

Sidebar, Header, and Footer render immediately. Only DataDisplay waits for data.

Alternative (share promise across components):

function Page() {
  // Start fetch immediately, but don't await
  const dataPromise = fetchData()

  return (
    <div>
      <div>Sidebar</div>
      <div>Header</div>
      <Suspense fallback={<Skeleton />}>
        <DataDisplay dataPromise={dataPromise} />
        <DataSummary dataPromise={dataPromise} />
      </Suspense>
      <div>Footer</div>
    </div>
  )
}

function DataDisplay({ dataPromise }: { dataPromise: Promise<Data> }) {
  const data = use(dataPromise) // Unwraps the promise
  return <div>{data.content}</div>
}

function DataSummary({ dataPromise }: { dataPromise: Promise<Data> }) {
  const data = use(dataPromise) // Reuses the same promise
  return <div>{data.summary}</div>
}

Both components share the same promise, so only one fetch occurs. Layout renders immediately while both components wait together.

When NOT to use this pattern:

  • Critical data needed for layout decisions (affects positioning)
  • SEO-critical content above the fold
  • Small, fast queries where suspense overhead isn't worth it
  • When you want to avoid layout shift (loading → content jump)

Trade-off: Faster initial paint vs potential layout shift. Choose based on your UX priorities.

本文档为站内渲染。原始文件本地路径:saas/source/knowledge-world/Knowledge-World-项目-Practice-Claude-Skills-vercel-react-best--f0cd05.md(仅本地保留,不入库不部署)