Description
Link to the code that reproduces this issue
https://stackblitz.com/edit/stackblitz-starters-ex8vzvqf?file=app%2Fpage.tsx
To Reproduce
- Start the application in development
- Observe the code inside
page.tsx
,components/client.tsx
andcomponents/server.tsx
. - Note what the children's type of the
InternalClientComponent
component
Current vs. Expected behavior
- The children of the
InternalClientComponent
should be of type:Symbol(React.element)
(orSymbol(React.transitional.element)
in react-19) - However, they are of type
Symbol(React.lazy)
indicating that they are suspending or awaiting smth, but they are not, they are a simple<button>
element.
IMPORTANT NOTES:
- Not passing the
data
property to either theClientComponent
orServerComponent
resolves the issue, pointing me that this is mostly related to the data reference, not the components themselves. - It is working with next@14
- If the
data
is of primitive type, it's also working - Not happening during
build
Provide environment information
Operating System:
Platform: linux
Arch: x64
Version: Ubuntu 20.04.0 LTS Sat Jan 11 2025 21:19:29 GMT+0200 (Eastern European Standard Time)
Available memory (MB): NaN
Available CPU cores: 8
Binaries:
Node: 18.20.3
npm: 10.2.3
Yarn: 1.22.19
pnpm: 8.15.6
Relevant Packages:
next: 15.2.0-canary.4 // Latest available version is detected (15.2.0-canary.4).
eslint-config-next: N/A
react: 19.0.0
react-dom: 19.0.0
typescript: 5.2.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
create-next-app, Turbopack, Webpack
Which stage(s) are affected? (Select all that apply)
next dev (local)
Additional context
I tested a different combinations of next 14/15 & react 18/19 as well as dev
& build
commands and with --turbo
flag and webpack respectively - the issue is consistently reproducable since next@15.0.0
I suspect that passing once a reference to a variable get's passed to a client component it gets turned to a promise so it can travel through the network, however there are also server component that are incorrectly reading the promise (instead of the original variable) which turns them into an async tree -> thus subsequent client components are receiving async
server components regardless if they are suspending or not.