Question about streaming and SEO: await + Suspense vs use() + Promise
Unanswered
Cape lion posted this in #help-forum
Cape lionOP
Hey everyone! I'm trying to understand the best approach for data fetching with streaming while maintaining good SEO. I have two patterns and I'm confused about which one to use:
Pattern 1: Server Component with await + Suspense
// app/page.tsx
import { Suspense } from 'react';
export default function Page() {
return (
<Suspense fallback={<Loading />}>
<HomeSection />
</Suspense>
);
}
// HomeSection.tsx (Server Component)
async function HomeSection() {
const data = await getHomeData();
return <div>{data.title}</div>;
}
Pattern 2: Client Component with use() + Promise
// app/page.tsx
export default function Page() {
const dataPromise = getHomeData();
return (
<Suspense fallback={<Loading />}>
<HomeSection dataPromise={dataPromise} />
</Suspense>
);
}
// HomeSection.tsx (Client Component)
'use client';
import { use } from 'react';
function HomeSection({ dataPromise }) {
const data = use(dataPromise);
return <div>{data.title}</div>;
}
My questions:
Do both patterns support streaming equally?
Is there any SEO difference between them? Does the HTML get rendered on the server in both cases?
When should I use Pattern 1 vs Pattern 2?
For a homepage that needs good SEO, which pattern is recommended?
I read the docs but I'm still confused about the practical differences. Thanks!
Pattern 1: Server Component with await + Suspense
// app/page.tsx
import { Suspense } from 'react';
export default function Page() {
return (
<Suspense fallback={<Loading />}>
<HomeSection />
</Suspense>
);
}
// HomeSection.tsx (Server Component)
async function HomeSection() {
const data = await getHomeData();
return <div>{data.title}</div>;
}
Pattern 2: Client Component with use() + Promise
// app/page.tsx
export default function Page() {
const dataPromise = getHomeData();
return (
<Suspense fallback={<Loading />}>
<HomeSection dataPromise={dataPromise} />
</Suspense>
);
}
// HomeSection.tsx (Client Component)
'use client';
import { use } from 'react';
function HomeSection({ dataPromise }) {
const data = use(dataPromise);
return <div>{data.title}</div>;
}
My questions:
Do both patterns support streaming equally?
Is there any SEO difference between them? Does the HTML get rendered on the server in both cases?
When should I use Pattern 1 vs Pattern 2?
For a homepage that needs good SEO, which pattern is recommended?
I read the docs but I'm still confused about the practical differences. Thanks!
1 Reply
Do both patterns support streaming equally?Yes. Both will trigger the Suspense boundary as soon as the
<HomeSection/>
starts to render and it encounters ‘await Promise’ or use(Promise)
. If the page is dynamically rendered, it will send the initial HTML up to the suspense boundary and then stream the component under the suspense boundary as soon as it resolves.
If the page is statically generated then no, the Suspense boundary won’t even get hit because the data will be fetched on the server, the page will be created and cached on the server and you’ll serve the cached version every time.
Does the HTML get rendered on the server in both cases?Yes, all components get pre-rendered on the server by default, server component and client components. The only way to opt out of this is by dynamically importing a component and setting SSR to false.
When should I use Pattern 1 (async - await) vs Pattern 2 (use)?Use first pattern
async await
whenever possible, if you’re in server component that natively support async operations then just await
the promise.The second pattern
use(Promise)
was introduced as a primitive React way to access to the the value of a promise (or context, but not relevant) in the attempt to make all component support async operations. Since client components do not support async await, yet, this is the way to go. Check this part of the [React docs](https://react.dev/reference/react/use#caveats)