gpt4 book ai didi

How can I use a react client sub-component inside a React Server Component?(如何在Reaction服务器组件中使用Reaction客户端子组件?)

转载 作者:bug小助手 更新时间:2023-10-25 09:33:54 24 4
gpt4 key购买 nike



I'm using Next.JS 13.4.19 with the new app folder to enable React Server Components, and running into issues trying to use client sub-components (i.e. <ClientComponent.SubComponent \>) inside a server component.

我将Next.JS 13.4.19与新的app文件夹一起使用,以启用Reaction服务器组件,并且在尝试使用服务器组件中的客户端子组件(即 )时遇到问题。


ClientTest.jsx is a Client component with sub-component attached (pretend this has some state or other reason to be client component)

Jsx是一个附加了子组件的客户端组件(假定这是客户端组件的状态或其他原因)


'use client'

export default function ClientTest() {
return <div>ClientTest</div>
}

ClientTest.Item = function ClientTestItem() {
return <div>ClientTest.Item</div>
}

page.jsx is a React Server Component (allows access to db or file system)

Jsx是一个Reaction服务器组件(允许访问数据库或文件系统)


import ClientTest from './ClientTest'

export default function Page() {
// ClientTest.Item is undefined, and the following line errors with:
// Unsupported Server Component type: undefined
return (
<ClientTest.Item />
);
}

it seems the main component <ClientTest /> works fine, but the attached <ClientTest.Item /> is undefined :(

主组件 似乎工作正常,但附加的 未定义:(


https://codesandbox.io/p/sandbox/currying-grass-wsvtn4?file=/app/page.tsx

Https://codesandbox.io/p/sandbox/currying-grass-wsvtn4?file=/app/page.tsx


Possible workaround would be to simply avoid sub-components in the server compoonent by making another wrapper client component (importing ClientTest.Item in a client component works fine) but I would greatly prefer if this could be fixed through some magic webpack configuration? or maybe it's a bug in next.js?

可能的解决方法是通过创建另一个包装器客户端组件(在客户端组件中导入ClientTest.Item可以很好地工作)来简单地避免服务器组件中的子组件,但我更希望通过一些神奇的webpack配置来解决这个问题?或者可能是next.js中的错误?


For the record; Importing server sub-components in server components works fine, as does importing client sub-components in client components.

需要指出的是,在服务器组件中导入服务器子组件很好,在客户端组件中导入客户端子组件也是如此。


Edit:

编辑:


I am working on a component library which uses the sub-component pattern quite a bit, so it makes a big difference to me if this is a "working as intended" part-of-the-design of server components, or a "current implementation limitation"/bug.

我正在开发一个组件库,它经常使用子组件模式,所以这是服务器组件设计的“按预期工作”部分,还是“当前实现限制”/错误,对我来说都有很大的不同。


If it is a permanent design limitation we might need to rethink our entire naming scheme and architecture to avoid terrible DX, but I haven't found anything conclusive about this in the react docs.

如果这是一个永久性的设计限制,我们可能需要重新考虑我们的整个命名方案和体系结构,以避免糟糕的DX,但我在Reaction文档中没有找到任何关于这一点的确凿证据。


更多回答
优秀答案推荐

You do everything right, this is the Next.js problem. I just wrote a broad explanation of this behaviour. Please see
https://stackoverflow.com/a/77077564/9047572

你做的每件事都是正确的,这就是Next.js的问题。我刚刚写了一篇关于这一行为的广泛解释。请参阅https://stackoverflow.com/a/77077564/9047572


TL:DR: you need that 'use client' directive to use client-only features. Once the component became client-side, its nested components are client-side too. No way to change or intercept this behavior.

TL:DR:您需要‘Use Client’指令才能使用仅限客户端的功能。一旦组件成为客户端,它的嵌套组件也是客户端。无法改变或拦截这种行为。



I've found a better workaround for my case (as library author who needs to publish client sub-components exposed to server components), and posting it here in case someone stumbles across the same issue;

我已经为我的案例找到了一个更好的解决方法(作为需要发布向服务器组件公开的客户端子组件的库作者),并将其发布在这里,以防有人遇到相同的问题;


Instead of attaching the sub-component inside the component file with use client, I can attach and re-export in a separate file. Using an index.js file I can keep the import path the same for consumers, and since this file does not have the 'use client' directive it will be parsed properly when imported in a React Server Component:

我可以在单独的文件中附加并重新导出,而不是使用Use Client附加组件文件中的子组件。使用index.js文件,我可以为消费者保持相同的导入路径,并且由于该文件没有‘Use Client’指令,因此在导入到Reaction服务器组件中时,它将被正确解析:


ClientTest/ClientTest.jsx

客户端测试/客户端测试.jsx


'use client'

export default function ClientTest() {
return <div>ClientTest</div>
}

ClientTest/ClientTest.Item.jsx

客户端测试/客户端测试.Item.jsx


'use client'

export default function ClientTestItem() {
return <div>ClientTest.Item</div>
}

ClientTest/index.js (note no 'use client' in this file)

ClientTest/index.js(注意此文件中没有‘使用客户端’)


import ClientTest from "./ClientTest";
import ClientTestItem from "./ClientTest.Item";

ClientTest.Item = ClientTestItem

export default ClientTest

page.jsx is as before, but should now work fine

Jsx与以前一样,但现在应该可以正常工作


import ClientTest from './ClientTest' // now uses ClientTest/index.js

export default function Page() {
return (
<ClientTest.Item />
);
}

Updated codesandbox:

更新后的codesandbox:


https://codesandbox.io/p/sandbox/eloquent-hooks-x3qgl8?file=/app/ClientTest/index.ts

Https://codesandbox.io/p/sandbox/eloquent-hooks-x3qgl8?file=/app/ClientTest/index.ts


更多回答

Thank you for sharing! However it doesn't seem to be quite the same issue, I'm not nesting components, but rather attaching a component as a property of the exported component. Sub-component !== children, if that makes sense :)

谢谢分享!然而,这似乎不是一个完全相同的问题,我不是在嵌套组件,而是将组件附加为导出组件的属性。子组件!==子组件,如果有意义的话:)

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com