Suspense fallback not showing in Layout.tsx
Answered
Blue swimming crab posted this in #help-forum
Blue swimming crabOP
I'm trying to show a loading state while an async component in my layout fetches data, but the Suspense fallback never shows up. Here's a minimal reproduction:
Instead of showing the "Loading..." fallback during the 3-second delay, the page just stays blank. What am I missing here? How can I properly show a loading state while the async component in my layout is fetching?
Using:
- Next.js 14.2.12
- App Dir
- Server Components
async function SlowComponent({ children }: { children: React.ReactNode }) {
// Artificial delay to simulate slow data fetching
await new Promise((resolve) => setTimeout(resolve, 3000));
return <div>{children}</div>;
}
export default function TestLayout({ children }: TestLayoutProps) {
return (
<div className="h-screen w-screen">
<Suspense fallback={<div>Loading...</div>}>
<SlowComponent>{children}</SlowComponent>
</Suspense>
</div>
);
}
Instead of showing the "Loading..." fallback during the 3-second delay, the page just stays blank. What am I missing here? How can I properly show a loading state while the async component in my layout is fetching?
Using:
- Next.js 14.2.12
- App Dir
- Server Components
Answered by Asian black bear
Looks like you're using Safari. Seems like something to do with this:
https://bugs.webkit.org/show_bug.cgi?id=252413
If your fallback is minimal (e.g. just "Loading ...") Safari might just not paint that.
https://bugs.webkit.org/show_bug.cgi?id=252413
If your fallback is minimal (e.g. just "Loading ...") Safari might just not paint that.
2 Replies
Asian black bear
Looks like you're using Safari. Seems like something to do with this:
https://bugs.webkit.org/show_bug.cgi?id=252413
If your fallback is minimal (e.g. just "Loading ...") Safari might just not paint that.
https://bugs.webkit.org/show_bug.cgi?id=252413
If your fallback is minimal (e.g. just "Loading ...") Safari might just not paint that.
Answer
Blue swimming crabOP
Thank you so much - this was brilliant! The WebKit bug report you linked helped me understand the root cause, and I found a neat workaround by playing into Safari's "heuristic".
Adding hidden text with sr-only (2 paragraphs worth) was enough to convince Safari that there's "meaningful content" to do first paint. Now loading state shows up perfectly in Safari too:
Really appreciate you pointing me in the right direction! 🙏
Adding hidden text with sr-only (2 paragraphs worth) was enough to convince Safari that there's "meaningful content" to do first paint. Now loading state shows up perfectly in Safari too:
<div className="sr-only" aria-hidden="true">
{Array.from({ length: 2 }).map((_, i) => (
<p key={i}>Loading content...</p>
))}
</div>
Really appreciate you pointing me in the right direction! 🙏