Next JS does server-side rendering on all components by default. If a component throws a promise during the server-side render, the client should see the nearest suspense boundary and the component shouldn't run client-side until the promise is resolved.
However, with the following setup (all on the root level), the Page component runs client-side as well even though the thrown promise never resolves. Removing ThemeProvider fixes the issue. I should note that removing loading.tsx also fixes the issue, although that's probably not the desired fix.
This is a dealbreaker for anyone using SSR + streamed hydration, since we want all components to fully render on the server (eg. with data) before being rendered on the client.
export default function Loading() {
return <div>Loading...</div>;
}
page.tsx
"use client";
export default function Home() {
console.log(
"you shouldn't see this client-side! (should only be logged on the server)"
);
throw new Promise(() => {});
}
What happened?
Next JS does server-side rendering on all components by default. If a component throws a promise during the server-side render, the client should see the nearest suspense boundary and the component shouldn't run client-side until the promise is resolved.
However, with the following setup (all on the root level), the Page component runs client-side as well even though the thrown promise never resolves. Removing
ThemeProvider
fixes the issue. I should note that removingloading.tsx
also fixes the issue, although that's probably not the desired fix.This is a dealbreaker for anyone using SSR + streamed hydration, since we want all components to fully render on the server (eg. with data) before being rendered on the client.
Minimum reproducible example: https://github.com/cirex-web/next-theme-ignored-suspense
layout.tsx
loading.tsx
page.tsx
Version
0.4.3
What browsers are you seeing the problem on?
Chrome