使用Next.js从Firebase取数时Safari出现Maximum call stack size exceeded错误
Maximum call stack size exceeded的问题 检查Firebase SDK版本兼容性:Safari对JS特性的支持和Chrome存在差异,老版本Firebase SDK可能藏着Safari专属的递归调用bug。试试升级到最新稳定版的
firebase/app、firebase/firestore等相关包,或者回退到已知兼容Safari的版本。严格控制数据获取的执行时机:哪怕用了
useMemo和useCallback,也得确认数据获取是不是在组件渲染周期里触发了无限重渲染。比如在客户端组件里,别在顶层直接调用数据获取函数,把它放进useEffect里,并且锁死依赖项:useEffect(() => { const fetchData = async () => { const doc = await getDoc(doc(db, 'collection', 'docId')); // 处理数据逻辑 }; fetchData(); }, []); // 空依赖确保只执行一次另外别把
setState函数直接丢进依赖数组,避免状态更新触发不必要的渲染循环。消除数据中的循环引用:Safari的JavaScriptCore引擎对递归栈的限制比Chrome的V8严格得多。检查处理Firebase返回数据的逻辑,有没有循环引用的对象——比如文档快照
data()返回的对象如果带循环引用,赋值给状态时就可能触发栈溢出。试试把数据转成纯JSON对象:const data = JSON.parse(JSON.stringify(doc.data()));这样能彻底消除循环引用,避免递归处理时炸栈。
临时禁用React Strict Mode测试:Next.js默认开了Strict Mode,开发环境会双重调用
useEffect、组件构造函数这类函数,Safari可能在这种重复执行下触发栈溢出。可以在next.config.js里先关掉试试:module.exports = { reactStrictMode: false, };如果关掉后问题消失,说明Strict Mode的重复执行暴露了Safari的专属bug,得再深挖数据处理里的副作用逻辑。
排查残留的实时监听器:哪怕改成了单次请求,也得确认有没有残留的Firestore实时监听器没移除,或者某些Firebase React绑定库在Safari下有内存泄漏导致的递归调用。如果之前用了
useCollectionData这类钩子,换成原生的getDoc/getDocs单次请求,同时确保所有监听器都正确调用unsubscribe清理。
内容的提问来源于stack exchange,提问作者Miguel

