Next.js 13 App Router组合按钮报错:Unsupported Server Component type: undefined
问题排查与解决:Unsupported Server Component type: undefined
错误原因
你的Header组件是Server Component(未添加"use client"指令),而Button是标记了"use client"的Client Component。在Next.js 13 App Router的服务端渲染阶段,Client Component的导出会被Next.js封装为特殊对象,你附加在Button上的静态属性(Button.Title、Button.Icon)会丢失,导致在Server Component中访问Button.Title时得到undefined,从而触发该错误。
解决方案
以下两种修复方式可根据需求选择:
方案1:直接导入子组件(推荐,保留Header为Server Component)
在Header组件中直接导入ButtonTitle,不再通过Button.Title的方式引用:
修改后的Header代码:
import { Logo } from "@/public"; import Image from "@/app/components/ui/image/image"; import React from "react"; import HeaderNav from "./nav/nav"; import Button from "@/app/components/ui/button/button"; // 直接导入子组件 import ButtonTitle from "@/app/components/ui/button/buttonTitle"; export default function Header() { return ( <header className="fixed top-0 left-0 right-0 max-w-[1440px] mx-auto flex-row-center max-h-[88px] px-2 py-6 backdrop-blur-[15px] bg-[rgba(77, 77, 77, 0.20)]"> <div className="flex-row-between w-full"> {/*logo */} <Image _css="h-[72px] w-[72px]" alt="logo" title="logo" src={Logo} /> {/* header menu links */} <HeaderNav /> <Button> {/* 直接使用导入的ButtonTitle */} <ButtonTitle>Reservation</ButtonTitle> </Button> </div> </header> ); }
方案2:将Header改为Client Component
如果Header需要处理客户端交互(如后续添加点击事件),可给Header添加"use client"指令,这样就能正常访问Button上的静态子组件:
修改后的Header代码:
"use client"; // 添加客户端组件标记 import { Logo } from "@/public"; import Image from "@/app/components/ui/image/image"; import React from "react"; import HeaderNav from "./nav/nav"; import Button from "@/app/components/ui/button/button"; export default function Header() { return ( <header className="fixed top-0 left-0 right-0 max-w-[1440px] mx-auto flex-row-center max-h-[88px] px-2 py-6 backdrop-blur-[15px] bg-[rgba(77, 77, 77, 0.20)]"> <div className="flex-row-between w-full"> {/*logo */} <Image _css="h-[72px] w-[72px]" alt="logo" title="logo" src={Logo} /> {/* header menu links */} <HeaderNav /> <Button> <Button.Title>Reservation</Button.Title> </Button> </div> </header> ); }
额外优化建议
若想保留组合式按钮的写法,可调整Button组件的导出方式,用命名导出代替静态挂载,示例如下:
修改Button组件文件:
"use client"; import React from "react"; import { motion } from "framer-motion"; import ButtonTitle from "./buttonTitle"; import { ButtonProps } from "./buttonProps"; import ButtonIcon from "./buttonIcon"; const Button = ({ children }: ButtonProps) => { return <motion.button className="btn btn-outlined">{children}</motion.button>; }; // 用命名导出代替静态挂载 export { Button, ButtonTitle as Title, ButtonIcon as Icon };
使用时的导入方式:
import { Button, Title as ButtonTitle } from "@/app/components/ui/button/button";
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

