vercel / next.js

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

The client component cannot get the type attribute of the child component. #68054

Open simonguo opened 1 month ago

simonguo commented 1 month ago

Link to the code that reproduces this issue

https://stackblitz.com/edit/stackblitz-starters-26sp4h

To Reproduce

// Item.tsx
'use client';

function Item({ children }) {
  return <div>{children}</div>;
}
export default Item;
//List.tsx
import Item from './item';

function List({ children }) {
  const items = React.Children.map(children, (child) => {

    // The child.type obtained here is an anonymous function. 
    // But I need to do something based on the type of the child component.
    console.log(child.type);

    return child;
  });

  return <div>{items}</div>;
}
// App.tsx

import List from './List';
import Item from './Item';

function App() {
  return (
    <List>
      <Item />
      <Item />
    </List>
  );
}

Current vs. Expected behavior

The Item and List in the above reproduction example may be components of material-ui or rsuite. These components declare use client in the file when exporting. As a result, when using server-side component rendering in Nextjs, the type of the component is an anonymous function, and the type of the component cannot be determined by type.

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: Ubuntu 20.04.0 LTS Tue Jul 23 2024 13:31:56 GMT+0800 (中国标准时间)
    Binaries:
      Node: 18.20.3
      npm: 10.2.3
      Yarn: 1.22.19
      pnpm: 8.15.6
    Relevant Packages:
      next: 13.5.1
      eslint-config-next: 13.5.1
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.2.2
    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), Other (Deployed)

Additional context

No response

AliRazaDev27 commented 1 month ago

Hello, to make this code work, you have to convert the component where your injecting the children to client component. for example, you have to make the App.tsx a client component so that List.tsx will also be automatically converted to client component and be aware of what children looks like(type etc.) You can wrap the code in App.tsx to another wrapper component (with "use client" defined) so that not all of your App becomes client component.