将服务器组件传递给客户端组件作为 Props 不起作用

问题描述 投票:0回答:1

当我尝试将服务器组件作为

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 个组件如下:

  • Nav - 客户端组件&这是在页面中导入的
  • AuthClientInOutWrapper - 客户端组件
  • AuthServerInOutForms - 服务器组件

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,但没有可用的。

另供参考:如果服务器组件直接放置在主布局中,它将按预期工作。问题是当服务器组件尝试传递到客户端组件时。

next.js next-auth react-server-components
1个回答
0
投票

<AuthServerInOutFormsCatto />
是一个服务器组件,但它在客户端组件中使用
<Nav />
,这是不可行的。

提到的技巧澄清了服务器组件只能在服务器组件内使用。为了实现所需的行为,您可以从服务器组件级别传递 Children 属性。

export const Nav = ({ children}) => { // ... <AuthClientInOutWrapperCatto> {children} </AuthClientInOutWrapperCatto> }
然后在layout.tsx(或渲染

<Nav />

的任何地方)将
<AuthServerInOutFormsCatto />
作为子项传递。


您不需要

"use server"

 文件顶部的 
AuthServerInOutForms
。你应该把它移到动作本身

<form action={async () => { "use server"; await signIn(); }} >
    
© www.soinside.com 2019 - 2024. All rights reserved.