NextJS中的一个新更新出来了(带app router)。我真的被客户端/服务器端组件关系搞糊涂了。我现在正在试用它,它在文档中说:
“使用客户端”位于仅服务器代码和客户端代码之间。它被放置在文件的顶部,在导入之上,以定义它从仅服务器到客户端部分的边界的截止点。一旦在文件中定义了“use client”,导入到其中的所有其他模块包括子组件都被视为client bundle的一部分。
下面是我的代码(Child.tsx):
import Parent from "./Parent";
import React, { useState } from 'react';
export default function Child() {
const [s, ss] = useState(null);
return (
<div>child</div>
)
}
父.tsx:
'use client';
import React, { useState } from 'react'
export default function Parent({children} : {
children: React.ReactNode
}) {
const [s, ss] = useState(null);
return (
<div>{children}</div>
)
}
page.tsx:
import Child from "./Child";
import Parent from "./Parent";
export default function Page() {
return (
<>
<Parent>
<Child />
</Parent>
</>
)
}
由于我的父组件有'use client'指令,根据文档,所有子组件也必须标记为客户端组件:
./app\Child.tsx
ReactServerComponentsError:
您正在导入一个需要useState的组件。它只能在客户端组件中工作,但它的父组件都没有标记为“使用客户端”,因此它们默认为服务器组件。
问题的原因是什么?
1条答案
按热度按时间plupiseo1#
我认为在这种情况下,Next.js文档有点误导。在您的案例中,
<Parent />
和<Child />
都在page.tsx
中定义,默认情况下,page.tsx
是服务器组件,在这种情况下,<Parent />
呈现为客户端,因为它具有'use client'
指令,但Child
呈现为服务器组件,因为它在服务器组件(page.tsx)中声明,并且没有'use client'
指令。<Child />
实际上是一个服务器组件,因此不能使用useState
。另一种看待这一点的方式是,<Parent />
在其children
属性中获得的是已经在page.tsx中呈现为服务器组件的<Child />
组件(html和css),而不是与<Parent />
沿着呈现的<Child />
组件声明。实际上,将一个服务器组件作为子组件传递给另一个服务器组件中的客户端组件是在客户端组件中拥有服务器组件的唯一方法。我知道这可能很难让你理解,我建议你看看https://nextjs.org/docs/getting-started/react-essentials#importing-server-into-client-components,他们有一些很好的例子。