所有组件在 Next.js 中都是客户端组件吗?

huangapple go评论61阅读模式
英文:

Is it normal that all components in Next.js are client components?

问题

以下是翻译好的部分:

我有一个Next应用程序。我使用应用程序文件夹和Next Auth库。为了使每个页面都能访问会话,我将整个应用程序包装在SessionProvider中。但由于它在底层使用了useContext,我不得不在每个地方添加'use client'指令。这导致所有页面都变成了客户端渲染,因为它们使用了useSession。并且所有页面组件(按钮、输入)也变成了客户端渲染。

app/layout.tsx

const RootLayout = ({ session, children }: { session: Session; children: ReactNode }) => {
	return (
		<SessionProvider session={session}>
			<html lang={`eng`} >
				<head>
				</head>
				<body>
					{children}
				</body>
			</html>
		</SessionProvider>
	)
}

一些受保护的页面

'use client';

import { useSession } from "next-auth/react";

export default function ProtectedPage() {
    const { data, status } = useSession()

    return (
        <div>
            {status === "authenticated" ? <div>{data.name}</div> : null}
        </div>
    )
}

所有页面和组件现在都在客户端渲染是否正常?Next Auth文档建议将所有内容都包装在提供程序中,但这样一来,Next.js的主要功能,即SSR,就不再起作用。

英文:

I have a Next app. I use app folder and Next Auth library. So that each page has access to the session, I wrapped the entire application in a SessionProvider. But since it's useContext under the hood, I had to add the &#39;use client&#39; directive everywhere. This resulted in all pages being client-side since they use useSession. And all page components (buttons, inputs) also became client-side.

app/layout.tsx

const RootLayout = ({ session, children }: { session: Session; children: ReactNode }) =&gt; {
	return (
		&lt;SessionProvider session={session}&gt;
				&lt;html lang={`eng`} 
					&lt;head&gt;
					&lt;/head&gt;
					&lt;body&gt;
						{children}
					&lt;/body&gt;
				&lt;/html&gt;
		&lt;/SessionProvider&gt;
	)
}

some protected page

&#39;use client&#39;;

import {useSession} from &quot;next-auth/react&quot;;

export default function ProtectedPage() {
    const {data, status} = useSession()


    return (
				&lt;div&gt;
					{status === &quot;authenticated&quot; ? &lt;div&gt;data.name&lt;/div&gt; : null}
				&lt;/div&gt;
    )
}

Is it normal that all pages and components are now rendered on the client? The Next Auth documentation recommends wrapping everything in a provider, but then the main feature of Next.js, namely SSR, no longer works

答案1

得分: 3

> 在Next.js中,所有组件都是客户端组件是正常的吗?

app文件夹下的每个组件默认都是服务器组件,意味着它在服务器端呈现,并且其代码保留在服务器端。

使用use client
> 所有页面和组件现在都在客户端上呈现是正常的吗?

您可以将服务器组件混合在客户端组件中作为其子组件。

<ClientComponent>
  <ServerComponent />
</ClientComponent>

有关更多详细信息,请阅读dev.to上的这篇文章

您可能还会对阅读medium上的这篇博客感兴趣。

英文:

> Is it normal that all components in Next.js are client components?

Every component under the app folder is, by default, a server component, meaning that it's rendered on the server side, and its code stays on the server side.

With use client
> Is it normal that all pages and components are now rendered on the client?

You can mix server component in client component as its children.

&lt;ClientComponent&gt;
  &lt;ServerComponent /&gt;
&lt;/ClientComponent&gt;

For further detail, read this article on dev.to.

You may also be interested to read this blog on medium.

答案2

得分: 1

以下是您要翻译的内容:

不,不是每个组件都需要成为客户端组件。您可以创建一个包装组件,它是一个客户端组件,接收子组件。服务器和客户端组件都可以作为子组件传递给客户端组件。

示例包装组件
"use client";

import NoAuthComponent from "components/NoAuthComponent";

interface Props extends React.PropsWithChildren {}

// 如果未经导入而作为属性提供未经身份验证的视图,您也可以将其设置为服务器组件
export default function ProtectedView({ children }: Props): JSX.Element {
  const session = useSession();
  if (session?.status !== "authenticated") return <NoAuthComponent />;
  return <>{children}</>;
}
示例用法
import "server-only";

import ProtectedView from "components/ProtectedView";
import MyServerComponent from "components/MyServerComponent";

export default async function MyPage(): Promise<JSX.Element> {
  const response = await fetch("...");
  const data = await response.json();
  return (
    <ProtectedView>
      <MyServerComponent data={data} />
    </ProtectedView>
  );
}

有关组合、嵌套和处理客户端和服务器组件的更多信息,请查看官方文档

英文:

No, not every component needs to be a client component. You could create a wrapper component that is a client component which receives children. Both server and client components can be passed to client components as children.

Example wrapper component
&quot;use client&quot;;

import NoAuthComponent from &quot;components/NoAuthComponent&quot;;

interface Props extends React.PropsWithChildren {}

// if the no auth view was provided as a prop rather then
// imported you could also make it a server component
export default function ProtectedView({ children }: Props): JSX.Element {
  const session = useSession();
  if (session?.status !== &quot;authenticated&quot;) return &lt;NoAuthComponent /&gt;;
  return &lt;&gt;{children}&lt;/&gt;;
}
Example usage
import &quot;server-only&quot;;

import ProtectedView from &quot;components/ProtectedView&quot;;
import MyServerComponent from &quot;components/MyServerComponent&quot;;

export default async function MyPage(): Promise&lt;JSX.Element&gt; {
  const response = await fetch(&quot;...&quot;);
  const data = await response.json();
  return (
    &lt;ProtectedView&gt;
      &lt;MyServerComponent data={data} /&gt;
    &lt;/ProtectedView&gt;
  );
}

More information about composing, nesting and working with client and server components can be found inside the official documentation.

huangapple
  • 本文由 发表于 2023年6月12日 17:40:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76455367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定