客户端组件调用Server Function触发栈溢出错误求助
解决React客户端组件调用Server Action时的栈溢出问题
问题原因
你遇到的maximum call stack size exceeded错误,核心原因是Mongoose查询返回的是带循环引用的文档对象,而非普通JavaScript对象。这些Mongoose文档包含大量内部方法和原型链引用,当Server Action将其返回给客户端时,序列化过程会因循环引用无限递归,最终导致调用栈溢出。
而服务端组件直接调用时,React Server Components在服务端处理这些对象,无需完整序列化到客户端;返回硬编码普通对象时不存在循环引用,因此都能正常运行。
解决方案
只需将Mongoose查询结果转换为普通JavaScript对象,消除循环引用即可,有两种常用方式:
方式1:使用.lean()查询(推荐)
.lean()是Mongoose内置方法,直接返回原生JS对象,跳过Mongoose文档实例的创建,性能更优:
修改@/actions/loads.js:
"use server" import connect from "@/helpers/db" import Loaddata from "@/models/loaddata" export async function getLoad(id) { await connect() if (id) { // 使用lean()返回普通JS对象 const data = await Loaddata.findById(id).lean() return data } // 使用lean()返回普通JS对象数组 const data = await Loaddata.find({}).lean() return data }
方式2:使用.toObject()转换已有文档
如果无法使用.lean(),可以将查询得到的Mongoose文档转换为普通对象:
修改@/actions/loads.js:
"use server" import connect from "@/helpers/db" import Loaddata from "@/models/loaddata" export async function getLoad(id) { await connect() if (id) { const data = await Loaddata.findById(id) // 将Mongoose文档转为普通对象 return data.toObject() } const data = await Loaddata.find({}) // 对数组中每个文档执行转换 return data.map(doc => doc.toObject()) }
验证
修改后重新调用Server Action,客户端组件就能正常接收和渲染数据,不会再出现栈溢出错误。
内容的提问来源于stack exchange,提问作者Brian Emilius
相关产品推荐
相关产品推荐

