Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[React 19] Bug: cloneElement in client component with async server component as children not working #32392

Open
darthmaim opened this issue Feb 15, 2025 · 3 comments
Labels

Comments

@darthmaim
Copy link

React version: 19

Steps To Reproduce

  1. Clone the reproduction
  2. npm i
  3. npm run dev
  4. Open http://localhost:3000/ and observe error

Link to code example: https://github.com/darthmaim-reproductions/vercel-next.js-72034

The current behavior

When using cloneElement in a client component, and the children is an async server component, this error is thrown:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of ClientComponent.

When the server component is not async (or a client component), this just works.

Additionally, adding this line to the client component also makes this work:

if(children.$$typeof === Symbol.for('react.lazy')) { children = use(children._payload); }

The expected behavior

Since cloneElement works for client components and non-async server components, I expected this to work with async server components as well.

Additional context

With react 18 the children was reported as <Lazy/> in react-dev-tools and cloneElement was working, now it is shown as { $$typeof: Symbol(react.lazy) } (when not using cloneElement to avoid the error).

I initially reported this is in the Next.js repo (vercel/next.js#72034), but I keep running into this bug and suspect its a react bug and not related to Next.js.

@umeshyadav7988
Copy link

Hey @darthmaim,

Thanks for reporting this issue!

It seems like React 19 handles async server components differently when passed as children to cloneElement. Given that in React 18, the component was recognized as <Lazy/> in dev tools but now appears as { $$typeof: Symbol(react.lazy) }, this suggests a potential change in how React processes async components internally.

Your workaround using:

if (children.$$typeof === Symbol.for('react.lazy')) {
children = use(children._payload);
}

suggests that React is treating async server components differently than expected, and cloneElement isn't automatically resolving them.

Some potential questions to investigate further:

  • Is this an intentional change in React 19, or an unintended regression?
  • Could cloneElement be enhanced to handle async server components, or should this be explicitly managed by developers?
  • Does this affect any other React APIs that interact with async server components?

@jlking18333
Copy link

This is my account originally and was done fraudulent

@darthmaim
Copy link
Author

Hey @jlking18333 / @umeshyadav7988,

please contact GitHub support to sort out your account issues, this is the react repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants