8000 `cloneElement` in client component with async server component as children not working · Issue #72034 · vercel/next.js · GitHub
[go: up one dir, main page]

Skip to content
cloneElement in client component with async server component as children not working #72034
@darthmaim

Description

@darthmaim

Link to the code that reproduces this issue

https://github.com/darthmaim-reproductions/vercel-next.js-72034

To Reproduce

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

Current vs. Expected behavior

Current

Expand to see relevant code

import { FC } from "react";
import { ClientComponent } from "./client-component";

export default function Home() {
  return (
    <ClientComponent>
      <ServerComponent/>
    </ClientComponent>
  );
}

const ServerComponent: FC = async () => <div>server component</div>
'use client'

import { cloneElement, FC, ReactElement, use } from "react"

export const ClientComponent: FC<{ children: ReactElement }> = ({ children }) => { 
  // @ts-ignore uncomment the next line for a workaround
  // if(children.$$typeof === Symbol.for('react.lazy')) { children = use(children._payload); }

  return cloneElement(children, {
    ref: (element) => console.log('ref', element)
  })
}

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); }

Expected

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

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 21.6.0: Mon Jun 24 00:56:10 PDT 2024; root:xnu-8020.240.18.709.2~1/RELEASE_X86_64
  Available memory (MB): 16384
  Available CPU cores: 4
Binaries:
  Node: 22.8.0
  npm: 10.8.2
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 15.0.2-canary.11 // Latest available version is detected (15.0.2-canary.11).
  eslint-config-next: N/A
  react: 19.0.0-rc-02c0e824-20241028
  react-dom: 19.0.0-rc-02c0e824-20241028
  typescript: 5.3.3
Next.js Config:
  output: N/A

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

Not sure

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

next dev (local), next build (local)

Additional context

This might be a bug in react and not in Next.js.

In earlier versions 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue was opened via the bug report template.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0