Next.js服务端与客户端组件通信:语言切换Cookie存储问题
问题原因
你遇到的报错「Event handlers cannot be passed to Client Component props.」是因为Next.js的服务端组件(Server Component)只能向客户端组件(Client Component)传递可序列化的props(如字符串、数字、普通对象),函数属于不可序列化类型,无法直接传递。另外,服务端的cookieStore是服务端环境专属API,不能在客户端调用,所以原来在服务端组件里定义的handleLanguageChange函数无法在客户端执行。
解决方案
把语言切换和Cookie操作的逻辑全部移到客户端组件中,服务端组件只负责传递初始的语言值(从服务端Cookie读取),避免跨组件传递函数。
修改后的服务端组件(Header)
import Link from "next/link"; import { Flex, Box } from "@chakra-ui/react"; import { boxStyles } from "../globalStyles"; import { cookies } from "next/headers"; import LangFlag from "./langFlag"; export default function Header() { const cookieStore = cookies(); // 从服务端Cookie获取当前语言,默认值设为'en' const currentLang = cookieStore.get("lang")?.value || "en"; return ( <header> <Flex flexDirection="row"> <Box sx={boxStyles}> <Link href="/">Home</Link> </Box> <Box sx={boxStyles}> <Link href="/answer">Answer</Link> </Box> <Box sx={boxStyles}> <Link href="/create">Create</Link> </Box> {/* 只传递可序列化的初始语言值,不再传函数 */} <LangFlag initialLang={currentLang} /> </Flex> </header> ); }
修改后的客户端组件(LangFlag)
"use client"; import { Box, Image } from "@chakra-ui/react"; import { useState, useEffect } from "react"; import { flagPictureStyle } from "../globalStyles"; // 客户端操作Cookie的辅助函数 const setLangCookie = (lang: string) => { // 设置Cookie,有效期30天,路径覆盖全站 document.cookie = `lang=${lang}; path=/; max-age=${30 * 24 * 60 * 60}; SameSite=Lax`; }; const getLangCookie = () => { // 从客户端Cookie中读取语言值 const langCookie = document.cookie.split("; ").find(item => item.startsWith("lang=")); return langCookie ? langCookie.split("=")[1] : ""; }; export default function LangFlag({ initialLang }: { initialLang: string }) { // 初始化语言:优先取客户端Cookie,没有则用服务端传递的初始值 const [lang, setLang] = useState(() => getLangCookie() || initialLang); // 根据语言设置对应的国旗图片 const [flag, setFlag] = useState(() => lang === "en" ? "img1" : "img2"); // 语言变化时同步更新Cookie useEffect(() => { setLangCookie(lang); }, [lang]); const changeLang = () => { const newLang = lang === "en" ? "se" : "en"; setLang(newLang); setFlag(newLang === "en" ? "img1" : "img2"); }; return ( <Box> <Image src={flag} alt={lang} sx={flagPictureStyle} onClick={changeLang} /> </Box> ); }
关键修改点
- 组件通信规则适配:服务端组件仅传递可序列化的初始语言值,避免传递函数触发报错。
- Cookie操作客户端化:用
document.cookie在客户端完成Cookie的读写,符合Next.js的环境限制。 - 状态一致性保障:初始化时优先读取客户端Cookie,确保服务端渲染和客户端交互的语言状态一致。
内容的提问来源于stack exchange,提问作者Ihrefjord
相关产品推荐
相关产品推荐

