Next.js 客户端组件函数 props 警告为何难以消除?

👁 72 次阅读

Next.js 客户端组件函数 props 警告为何难以消除?

来源链接:https://github.com/vercel/next.js/issues/74343

现象描述

在 Next.js 项目的 "use client" 文件中,只要组件接收函数、state 的 dispatch,或任何不可序列化的 props,TypeScript(由 Next.js 版本携带的类型检查)就会给出警告,提示开发者要么把 props 改为可序列化,要么把 prop 名加上 Action 后缀。issue 提交者指出,这一限制已经导致大量不必要的重命名,而其中大部分场景与 Server Actions 毫无关系。 issue 给出的复现说明非常简短:
just create any component in a "use client" file that accepts a function, dispatch for state, or anything that is non-serializable as props.
issue 提交者同时声明不提供最小复现,认为所引用的讨论帖已包含足够上下文,并把复现链接指向 https://github.com/vercel/next.js/discussions/46795 。 提交环境信息如下:
Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 24.0.0: Mon Aug 12 20:54:30 PDT 2024; root:xnu-11215.1.10~1/RELEASE_X86_64
  Available memory (MB): 32768
  Available CPU cores: 16
Binaries:
  Node: 22.9.0
  npm: 10.8.3
  Yarn: N/A
  pnpm: 9.12.0
Relevant Packages:
  next: 15.1.1-canary.16 // There is a newer canary version (15.1.1-canary.22) available, please upgrade!
  eslint-config-next: 14.2.11
  react: 19.0.0-rc-603e6108-20241029
  react-dom: 19.0.0-rc-603e6108-20241029
  typescript: 5.6.2
Next.js Config:
  output: N/A
受影响范围被标记为 Developer Experience、Linting、Partial Prerendering(PPR),受影响阶段为 next dev(本地)。

背景原因

社区成员 pawelblaszczyk5 在讨论中给出了框架设计层面的解释:"use client" 应当只用于标记客户端与服务端代码之间的边界,类似 "use server",而不是给每一个客户端组件都加上。边界本身带有额外限制,例如 props 必须可序列化。该成员进一步强调,"use server" 与 "use client" 并非 Next.js 独有的功能,而是 React 特性,Next.js 只是在你违反 React 规则时给出警告。 issue 提交者 inducingchaos 对这一说法提出反对,认为把问题归给 React 并不能解决在 Next.js 中遇到的实际问题,并指出这是框架内真实存在的、需要投入更多精力处理的问题。讨论由此进入长期拉锯。 React 团队成员 gaearon 参与了后期讨论。有用户 OrhanTozan 在 2025-10-27 总结自己的理解:当客户端组件带有 onClick 这类事件 props 时警告出现是合理的,因为接受事件 prop 的组件本身无法被服务端调用,所以也许不应该遵循“给每个客户端组件都加 "use client"”的流行惯例。gaearon 在 2025-10-28 回复认可这一理解,并补充 "use server" 的含义是“可被客户端直接调用”。 h3rmanj 在 2025-11-19 对讨论中“服务端无法直接 import Bar”的说法提出反例,指出可以从服务端传入另一个被标记为 client 的函数:
"use client"

export function Bar({ onClick }: { onClick?: () => {} }) {
  return <div onClick={onClick} />
}
"use client"

export function doSomething() {
  alert("click")
}

排查或量化方法

issue 提交者 inducingchaos 在 2026-02-03 回到讨论中,用官方项目来量化问题的影响面,指出 Vercel 官方的 Chat SDK(ai-chatbot)同样触发该警告,并给出具体文件位置:
https://github.com/vercel/ai-chatbot/blob/main/hooks/use-auto-resume.ts#L11-L12
在编辑器中呈现的完整警告文本为:
Props must be serializable for components in the "use client" entry file. "resumeStream" is a function that's not a Server Action. Rename "resumeStream" either to "action" or ...
这条警告文本说明了当前规则的两个可操作出口:改为可序列化 props,或把 prop 名重命名为 action(含 Action 前缀/后缀形式)。用官方仓库的实例来核对,是判断该规则误报范围最直接的方式。

完整解决方案(当前处理路径与局限)

该 issue 截至最后一条评论日期(2026-05-04)仍为 open 状态,官方尚未合入框架层方案。评论中出现的处理路径有三类。 路径一:按警告提示重命名 props。 把函数类型的 prop 改名为 action 或加上 Action 后缀,即可让警告消失。issue 提交者本人指出这正是问题所在——大量与 Server Actions 无关的 props 被迫改名。 路径二:调整 "use client" 的放置位置。 按 pawelblaszczyk5 与 gaearon 认可的模型,"use client" 只应标记客户端与服务端之间的边界文件,而非每个客户端组件。把边界文件收窄,可以让边界内的普通客户端组件自由接收函数 props,因为它们不再位于 "use client" 入口文件的判定范围内。 路径三:使用社区 ESLint 插件。 用户 sbougerel 在 2026-02-20 表示创建了一个 linter 来帮助确保 'use client'; 模块中的组件入口具有可序列化属性:
https://github.com/sbougerel/eslint-plugin-next-use-client-boundary
该插件属于社区方案,据 issue 讨论发布,需自行评估是否适配现有项目。 issue 提交者 inducingchaos 在 2026-05-04 表示,如果自己还在更多使用 Next.js,会直接提 PR,或用 pnpm 打补丁让该警告可被静默,直到官方维护者选定方向。这条表述说明补丁式静默是社区讨论中出现的想法之一,但截至最后一条评论并无对应的 PR 记录出现在评论中。

参数或对比表格

下表汇总评论中出现的三种处理路径及其代价,内容均来自 issue 讨论。
处理路径具体动作代价或局限
重命名 props把函数 prop 改名为 action 或加 Action 后缀与 Server Actions 无关的场景也被迫改名,issue 提交者称之为不必要重命名
收窄 "use client" 边界只在客户端与服务端交界文件上使用 "use client"需要改动项目结构习惯,且与“每个客户端组件都标记”的流行惯例相反
接入社区 ESLint 插件使用 eslint-plugin-next-use-client-boundary属社区方案,非官方支持

常见错误排查

警告中的 prop 名与实际不符。 需核对警告文本里给出的 prop 名,例如官方 ai-chatbot 场景中的 resumeStream,再决定是重命名还是调整边界。 误以为是类型错误。 该提示由 Next.js 版本携带的 TypeScript 检查给出,并非 React 或 TypeScript 本身的类型错误,重命名 props 即可消除,不涉及类型定义修改。 把 "use client" 当作组件级标记。 pawelblaszczyk5 指出 "use client" 是边界标记而非组件标记,把它加在每个客户端组件上会持续触发该规则。 认为该警告只影响 Server Actions。 讨论中反复确认,触发场景包含事件回调、state dispatch 等一切与客户端-服务端边界无关的不可序列化 props。

实践建议

把 "use client" 用在真正的客户端-服务端边界文件上,而不是每个客户端组件。gaearon 认可的解释是:接受事件 prop 的组件本身无法被服务端调用,因此对这类组件加 "use client" 反而制造了冲突。当组件在客户端组件之间层层嵌套时,把边界放在最外层,内层组件即可自由传递函数 props。 对无法调整结构、又需要长期维护的项目,可评估是否接入社区 ESLint 插件,或在构建流程中通过包管理器打补丁静默警告——后者在 issue 讨论中被提出,但截至最后一条评论没有官方支持。该静默功能的具体实现尚未公开,官方也未提供对应的 tsconfig 开关。

FAQ

这个警告是错误还是提示? 它是 Next.js 携带的检查在检测到 "use client" 入口文件中存在不可序列化 props 时给出的提示,讨论中对其是否该在此场景触发存在持续争议。 issue 目前是什么状态? open。最后一条实质评论日期为 2026-05-04,共 59 条实质评论,无关闭时间与关闭原因。 官方是否已给出修复版本? 没有。评论中未出现维护者确认的修复版本号,官方也未提供关闭该警告的配置项。 社区有哪些可用方案? 社区成员 sbougerel 发布了 ESLint 插件 eslint-plugin-next-use-client-boundary,另有讨论中提出的包管理器补丁静默思路。 为什么官方项目自己也会触发? issue 提交者指出 Vercel 官方 ai-chatbot 的 hooks/use-auto-resume.ts 触发同一警告,说明该规则在官方示例中同样会误报。

订阅 AI 百事知

每周精选 AI 工具评测、行业资讯与使用教程,第一时间送达。

🔗 相关阅读(你可能还想看)

📄 Outlook 节点创建草稿添加附件为何报 UnableToDeserializePostBody?
📄 Flowise 点击市场或聊天页为何整页白屏?
📄 如何解决 Azure AI Search 向量存储的 $filter 递归深度超限错误?
📄 如何解决 shadcn/ui Sidebar 与 Header 重叠的问题?
📄 Next.js 开发服务器为何会 JavaScript heap out of memory?
📄 Nuxt 偶发 Cannot read properties of undefined 报错是怎么回事
📄 如何解决「Visual Studio Code for ipad」相关的问题?
📄 如何在AutoGen中实现企业级代理治理的加密行动收据(AAR)?
📄 记忆内容未清洗直接注入系统提示词,如何防范间接提示注入?
crewAI LiteAgent 将记忆内容直接拼接到系统提示词,存在间接提示注入风险。社区提出分层防御方案,但 iss
🤖 想直接和 AI 对话?
免费体验 DeepSeek V4 等顶级模型,无需注册,随问随答
🎯 立即体验 AI 工具

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

🤖 嘟嘟客服
滚动至顶部
🤖 嘟嘟客服
🤖 嘟嘟客服
';i.value='';m.innerHTML+='
...
';fetch('/dify-chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({query:q,user:'w'+Date.now()})}).then(function(r){return r.json()}).then(function(d){var a=d.answer||'暂时无法回复';m.removeChild(m.lastChild);m.innerHTML+='
'+a+'
'}).catch(function(){m.removeChild(m.lastChild);m.innerHTML+='
网络异常
'})">发送