vercel / next.js

The React Framework
https://nextjs.org
MIT License
127.41k stars 27.03k forks source link

[RSC] Nested Promises in multiple suspense boundaries #59735

Open kspeyanski opened 11 months ago

kspeyanski commented 11 months ago

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/suspense-nested-promise-33zfhn?file=%2Fapp%2Fmodels.tsx%3A14%2C1

To Reproduce

  1. Navigate to the server.tsx file
  2. replace line 10 with line 12
  3. Look for a server error in the console

Current vs. Expected behavior

I would expect the example to not throw.

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 14.0.5-canary.17
  eslint-config-next: 14.0.5-canary.17
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure, App Router

Additional context

Logging:A previously unvisited boundary must have exactly one root segment..

Seems like back-to-back promises does not work great with Suspense in the specific scenario where a parent node introduces a suspense boundary which's fallback actually want's to continue rendering it's children — I'm really believe this is a valid scenario.

It's possible that this bug is in the react package itself as the report log's indicate, but it's hardly reproducible outside of NextJS + app router + RSC.

bartoszhernas commented 1 month ago

I have the same problem, basically boils down to

Outside Component:

<Suspense fallback={<InsideCompoent data={undefined} />}>
    <InsideComponentLoader id={1} /> {/* it loads data with promise and show as <InsideComponent data={data} /> *}
</Suspense>

Then if inside components has it's own Suspense, this error mentioned here happens.

Current solution is to just not use Suspene inside Suspense's fallback at all, which is a bummer, because it leaves you only with suspense waterfall or one big suspense for everything.