next.js 报错“event handlers cannot be passed to client component props”通常并非因缺失 `”use client”`,而是因服务端组件意外接收了客户端专属 prop(如 `onclick`),根本原因在于模块导出链未正确标记客户端边界。
在 Next.js 中,”use client” 是一个编译时指令,用于明确划分客户端组件边界,并触发 React Server Components(RSC)架构下的客户端 hydration 流程。但仅在组件实现文件(如 Button.js)顶部添加 “use client” 并不足够——该指令必须作用于被实际导入(import)的入口模块,否则 Next.js 构建系统无法识别该模块应作为客户端上下文执行,仍会将其视为服务端组件处理,导致事件处理器(如 onClick)被拒绝传递。
例如,你定义的组件看似合规:
// node_modules/your-package/Button/Button.js
"use client";
import * as React from "react";
export const Button = () => {
return <button onClick={() => alert("boop")}>Boop</button>;
};
但如果应用中直接通过 import { Button } from “your-package/Button/Button” 导入,Next.js 实际解析的是未声明 “use client” 的 包内中间导出文件(如 node_modules/your-package/Button/index.js),而该文件默认被视为服务端模块。此时,即使 Button.js 内部有 “use client”,其导出内容仍被父级服务端模块“污染”,最终导致 onClick 被拦截并抛出错误。
✅ 正确做法是:在直接被项目 import 的入口文件(即导出路径的最上层 index 文件)中声明 “use client”: