Next.js 13.5 App Router:服务端页面传props到客户端组件未定义
问题:Next.js 13.5 App Router中服务端页面向客户端组件传递Props值为undefined
我正在使用Next.js v13.5的App Router,拥有一个/dashboard服务端页面,页面内包含ApiKeyOptions客户端组件。当我从dashboard页面向ApiKeyOptions组件传递props时,获取到的值为undefined。其他功能都正常运行,没有报错,只是key props的值为undefined。
/dashboard 服务端页面代码
import ApiKeyOptions from "@/components/client-compoents/ApiKeyOptions"; import KeyStatics from "@/components/client-compoents/KeyStatics"; import RequestApiKey from "@/components/client-compoents/RequestApiKey"; import authoptions from "@/lib/authOptions"; import { db } from "@/lib/db/db"; import { getServerSession } from "next-auth"; import React from "react"; const page = async () => { const session = await getServerSession(authoptions); const apiKey = await db.apiKey.findFirst({ where: { userId: session?.user.id, enabled: true, }, }); return ( <section className="container mt-24 sm:px-16 "> <div className="flex w-full justify-between items-center"> <h2> Howdy, <span className="font-medium">{session?.user.name} ?</span> </h2> <img src={session?.user.image!} alt={session?.user.name as string} width={45} height={45} referrerPolicy="no-referrer" className="border-2 border-solid border-slate-500 p-[2px] rounded-full" /> </div> {apiKey && ( <div className="flex items-center gap-x-4 mt-2"> <h2 className="font-light text-sm p-2 bg-[rgba(0,0,0,0.15)] w-fit rounded-md"> {apiKey?.key} </h2> <ApiKeyOptions key={"whatever"} /> </div> )} <div className="flex justify-center mt-6"> {apiKey ? <KeyStatics /> : <RequestApiKey />} </div> </section> ); }; export default page;
ApiKeyOptions 客户端组件代码
"use client"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { DotsVerticalIcon } from "@radix-ui/react-icons"; import { useToast } from "../ui/use-toast"; export default function ApiKeyOptions({ key }: { key: string }) { console.log(key); const { toast } = useToast(); function copyText(text: string) { navigator.clipboard.writeText(text); toast({ description: "Copied to clipboard.", }); } return ( <DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" size="icon"> <DotsVerticalIcon className="h-4 w-4" /> </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-40 dark:bg-slate-700 text-left"> <Button variant="ghost" className="block w-full hover:dark:bg-slate-800 text-left" // onClick={() => copyText(key)} > Copy </Button> <DropdownMenuSeparator /> <Button variant="ghost" className="block w-full hover:dark:bg-slate-800 text-left" > Revoke </Button> <DropdownMenuSeparator /> </DropdownMenuContent> </DropdownMenu> ); }
解决方案
问题根源
key是React的特殊保留属性,专门用于在列表渲染场景中标识组件实例,帮助React高效更新DOM。这个属性会被React内部处理,不会作为普通props传递给组件,所以你在ApiKeyOptions中尝试获取key时得到的是undefined。
修复步骤
修改服务端页面的props传递名称
将传递的props名称从key改为自定义名称(比如apiKey),同时传递真实的API密钥值:// 在/dashboard页面中修改组件调用 <ApiKeyOptions apiKey={apiKey.key} />如果你需要给组件设置React的
key属性(比如后续有列表渲染场景),可以同时添加:<ApiKeyOptions key={apiKey.id} apiKey={apiKey.key} />修改客户端组件的props接收逻辑
同步修改组件的props接收参数,并更新相关逻辑:// ApiKeyOptions组件中修改 export default function ApiKeyOptions({ apiKey }: { apiKey: string }) { console.log(apiKey); // 现在会输出正确的API密钥 const { toast } = useToast(); function copyText(text: string) { navigator.clipboard.writeText(text); toast({ description: "Copied to clipboard.", }); } return ( <DropdownMenu> {/* ... 其他代码 */} <Button variant="ghost" className="block w-full hover:dark:bg-slate-800 text-left" onClick={() => copyText(apiKey)} // 这里改为apiKey > Copy </Button> {/* ... 其他代码 */} </DropdownMenu> ); }
验证
完成修改后,重新运行项目,ApiKeyOptions组件就能正确接收到传递的API密钥值,复制功能也可以正常使用。
内容的提问来源于stack exchange,提问作者Pawan Poudel
相关产品推荐
相关产品推荐

