当我尝试将服务器组件作为
next-auth v5
实现中的 Next.js v14
的道具传递给客户端组件时,出现错误。我试图在下一个网站上遵循这种模式https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#supported-pattern-passing-server-components-to-client- Components-as-props 将服务器组件传递给客户端组件。错误是:
错误:客户端组件尚不支持 async/await,仅服务器组件支持。此错误通常是由于意外将
添加到最初为服务器编写的模块而引起的。'use client'
需要更改什么才能解决此错误?
这 3 个组件如下:
AuthClientInOutWrapper:
"use client";
import React from "react";
async function AuthClientInOutWrapper({
children
}: {
children: React.ReactNode;
}) {
return (
<>
{children}
</>
);
}
export default AuthClientInOutWrapper;
AuthServerInOutForms
"use server";
import { auth, signIn, signOut } from "auth";
async function AuthServerInOutForms() {
const session = await auth();
return (
<>
{session && session.user ? (
<>
<h1>sign out 44</h1>
<form
action={async () => {
await signOut();
}}
>
<button className="text-white" type="submit">Sign Out 44</button>
</form>
</>
) : (
<>
<h1>sign in 44</h1>
<form
action={async () => {
await signIn();
}}
>
<button className="text-white" type="submit">Sign In 44</button>
</form>
</>
)}
</>
);
}
export default AuthServerInOutForms;
导航客户端组件:
<AuthClientInOutWrapper>
<AuthServerInOutForms />
</AuthClientInOutWrapper>
简化的导航完整组件:
'use client';
import React, { ReactNode, useState } from 'react';
import Link from 'next/link';
import AuthClientInOutWrapperCatto from '../UI-client-server/AuthClientInOutWrapperCatto/AuthClientInOutWrapperCatto';
import AuthServerInOutFormsCatto from '../UI-client-server/AuthServerInOutFormsCatto/AuthServerInOutFormsCatto';
const Nav = () => {
const [isNavOpen, setIsNavOpen] = useState(false);
const handleCloseAllClick = () => {
setIsNavOpen(false);
};
return (
<>
<nav className="border-gray-200 bg-white dark:bg-gray-900">
<div className="mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4">
{/* Main Nav Level-1 Section */}
<div>
<ul className=" flex flex-col rounded-lg border border-gray-100 bg-gray-50 p-4 font-medium rtl:space-x-reverse dark:border-gray-700 dark:bg-gray-800 md:mt-0 md:flex-row md:space-x-8 md:border-0 md:bg-white md:p-0 md:dark:bg-gray-900">
{/* Home Link */}
<li>
<Link
href="/"
onClick={handleCloseAllClick}
>
Home
</Link>
</li>
{/* About Link */}
<li>
<Link
href="/about"
onClick={handleCloseAllClick}
>
<span>About</span>
</Link>
</li>
<AuthClientInOutWrapperCatto>
<AuthServerInOutFormsCatto />
</AuthClientInOutWrapperCatto>
</ul>
</div>
</div>
</nav>
</>
);
};
export default Nav;
编辑:感谢艾哈迈德·阿卜杜勒巴塞特的评论。我删除了服务器组件 AuthServerInOutForms 顶部的“使用服务器”行,然后页面呈现,但是登录按钮不可单击,并且在控制台中出现此错误:
未捕获(承诺中)错误:不变: headers() 期望有 requestAsyncStorage,但没有可用的。
另供参考:如果服务器组件直接放置在主布局中,它将按预期工作。问题是当服务器组件尝试传递到客户端组件时。
<AuthServerInOutFormsCatto />
是一个服务器组件,但它在客户端组件中使用<Nav />
,这是不可行的。
提到的技巧澄清了服务器组件只能在服务器组件内使用。为了实现所需的行为,您可以从服务器组件级别传递 Children 属性。
export const Nav = ({ children}) => {
// ...
<AuthClientInOutWrapperCatto>
{children}
</AuthClientInOutWrapperCatto>
}
然后在layout.tsx(或渲染<Nav />
的任何地方)将
<AuthServerInOutFormsCatto />
作为子项传递。
"use server"
文件顶部的
AuthServerInOutForms
。你应该把它移到动作本身
<form
action={async () => {
"use server";
await signIn();
}}
>