Header无法作为JSX组件使用:返回类型Promise不是有效JSX元素
问题:Header组件无法作为JSX使用,返回Promise而非有效JSX元素
报错信息:Header cannot be used as a JSX component. Its return type 'Promise' is not a valid JSX element. Type 'Promise' is missing the following properties from type 'ReactElement<any, any>': type, props, key
原代码实现
import Image from "next/image"; import Link from "next/link"; import LogoutButton from "./LogoutButton"; import { unstable_getServerSession } from "next-auth/next"; async function Header() { const session = await unstable_getServerSession(); if (session) return ( <header className="sticky top-0 z-50 bg-white flex justify-between items-center p-10 shadow-sm"> <div className="flex space-x-2"> <Image className="rounded-full mx-2 object-contain" height={10} width={50} src={session.user?.image!} alt="Profile Picture" /> <div> <p className="text-blue-400">Logged in as:</p> <p className="font-bold text-lg">{session.user?.name}</p> </div> </div> <LogoutButton /> </header> ); return ( <header className="sticky top-0 z-50 bg-white flex justify-center items-center p-10 shadow-sm"> <div className="flex flex-col items-center space-y-5"> <div className="flex space-x-2 items-center"> <Image src="https://links.papareact.com/jne" height={10} width={50} alt="Logo" /> <p className="text-blue-400">Welcome to Meta Messenger</p> </div> <Link href="/auth/signin" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Sign In </Link> </div> </header> ); } export default Header;
问题原因
React(Next.js Pages Router)不支持将async函数作为组件使用,因为async函数的返回值是Promise,而JSX组件要求返回ReactElement类型的结果,两者类型不匹配导致报错。
解决方法
方法1:在页面的getServerSideProps中获取session,传入Header组件
在使用Header的页面组件中,通过getServerSideProps获取session,再作为props传递给Header:
// 页面组件(比如pages/index.js) import Header from '../components/Header'; import { unstable_getServerSession } from "next-auth/next"; import { authOptions } from "../pages/api/auth/[...nextauth]"; // 引入你的auth配置 export async function getServerSideProps(context) { const session = await unstable_getServerSession(context.req, context.res, authOptions); return { props: { session } }; } export default function Home({ session }) { return ( <> <Header session={session} /> {/* 页面其他内容 */} </> ); }
修改Header组件,去掉async逻辑,直接接收props中的session:
// Header组件 import Image from "next/image"; import Link from "next/link"; import LogoutButton from "./LogoutButton"; function Header({ session }) { if (session) return ( <header className="sticky top-0 z-50 bg-white flex justify-between items-center p-10 shadow-sm"> <div className="flex space-x-2"> <Image className="rounded-full mx-2 object-contain" height={10} width={50} src={session.user?.image!} alt="Profile Picture" /> <div> <p className="text-blue-400">Logged in as:</p> <p className="font-bold text-lg">{session.user?.name}</p> </div> </div> <LogoutButton /> </header> ); return ( <header className="sticky top-0 z-50 bg-white flex justify-center items-center p-10 shadow-sm"> <div className="flex flex-col items-center space-y-5"> <div className="flex space-x-2 items-center"> <Image src="https://links.papareact.com/jne" height={10} width={50} alt="Logo" /> <p className="text-blue-400">Welcome to Meta Messenger</p> </div> <Link href="/auth/signin" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Sign In </Link> </div> </header> ); } export default Header;
方法2:使用客户端数据获取工具(如SWR)在Header内部获取session
如果不想在页面层传递props,可以用SWR在客户端获取session:
首先安装SWR:
npm install swr # 或 yarn add swr
修改Header组件:
import Image from "next/image"; import Link from "next/link"; import LogoutButton from "./LogoutButton"; import useSWR from 'swr'; // 定义获取session的函数 const fetcher = async () => { const res = await fetch('/api/auth/session'); const data = await res.json(); return data; }; function Header() { const { data: session } = useSWR('/api/auth/session', fetcher); // 可选:处理加载状态 if (session === undefined) { return <header className="sticky top-0 z-50 bg-white p-10 shadow-sm">Loading...</header>; } if (session) return ( <header className="sticky top-0 z-50 bg-white flex justify-between items-center p-10 shadow-sm"> <div className="flex space-x-2"> <Image className="rounded-full mx-2 object-contain" height={10} width={50} src={session.user?.image!} alt="Profile Picture" /> <div> <p className="text-blue-400">Logged in as:</p> <p className="font-bold text-lg">{session.user?.name}</p> </div> </div> <LogoutButton /> </header> ); return ( <header className="sticky top-0 z-50 bg-white flex justify-center items-center p-10 shadow-sm"> <div className="flex flex-col items-center space-y-5"> <div className="flex space-x-2 items-center"> <Image src="https://links.papareact.com/jne" height={10} width={50} alt="Logo" /> <p className="text-blue-400">Welcome to Meta Messenger</p> </div> <Link href="/auth/signin" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Sign In </Link> </div> </header> ); } export default Header;
方法3:如果使用Next.js 13+ App Router,将Header改为Server Component
如果你的项目用的是App Router(目录结构为app/),可以直接保留async组件,因为App Router默认支持Server Component(无需额外配置,只要组件未使用客户端钩子如useState、useEffect即可):
// app/components/Header.jsx import Image from "next/image"; import Link from "next/link"; import LogoutButton from "./LogoutButton"; import { unstable_getServerSession } from "next-auth/next"; import { authOptions } from "../api/auth/[...nextauth]/route"; // 对应App Router的auth配置路径 async function Header() { const session = await unstable_getServerSession(authOptions); if (session) return ( <header className="sticky top-0 z-50 bg-white flex justify-between items-center p-10 shadow-sm"> <div className="flex space-x-2"> <Image className="rounded-full mx-2 object-contain" height={10} width={50} src={session.user?.image!} alt="Profile Picture" /> <div> <p className="text-blue-400">Logged in as:</p> <p className="font-bold text-lg">{session.user?.name}</p> </div> </div> <LogoutButton /> </header> ); return ( <header className="sticky top-0 z-50 bg-white flex justify-center items-center p-10 shadow-sm"> <div className="flex flex-col items-center space-y-5"> <div className="flex space-x-2 items-center"> <Image src="https://links.papareact.com/jne" height={10} width={50} alt="Logo" /> <p className="text-blue-400">Welcome to Meta Messenger</p> </div> <Link href="/auth/signin" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" > Sign In </Link> </div> </header> ); } export default Header;
内容的提问来源于stack exchange,提问作者anasryadi
相关产品推荐
相关产品推荐

