如何解决Nuxt.js+Vuex场景下Maximum call stack size exceeded错误
兄弟,你这个问题是典型的无限递归调用导致的栈溢出,我帮你拆解下问题根源和解决步骤:
首先看你写的代码,你定义了一个叫setPosts的action,而它的内部又直接调用了同名的mutation setPosts——关键是这个action完全是多余的!它没有任何异步逻辑,只是单纯把参数转发给mutation,这种写法不仅没必要,还容易埋下循环调用的隐患。
问题根源分析
出现栈溢出的最大可能是:某个地方不小心触发了这个setPosts action,mutation修改state后,又被某个监听(比如组件里的watch)捕捉到,进而再次触发action,形成了action → mutation → state变化 → 监听触发action → ...的无限循环,最终把调用栈撑爆了。
排查&解决步骤
我给你一步步梳理:
删掉多余的
setPostsaction
既然它只是转发commit,没有任何额外逻辑(比如异步请求、数据处理),完全可以直接在需要的地方commit mutation,没必要多这一层冗余。检查
setPostsmutation的实现
确保mutation是纯同步的纯函数,直接修改state就行,别搞多余操作。比如正确的写法应该是:mutations: { setPosts(state, posts) { // 直接替换数组(你是从Firebase拿全量数据,直接替换比追加更合理) state.posts = posts; } }排查循环触发的源头
去检查你的组件、watch、computed里,有没有在state.posts变化后,又触发setPosts的action或者mutation?比如这种错误写法:// 组件里错误的watch示例 watch: { '$store.state.posts'(newPosts) { // 这里又dispatch了setPosts,直接导致循环 this.$store.dispatch('setPosts', newPosts) } }如果有这种代码,要么删掉,要么加个条件判断,避免无限触发。
检查命名冲突
如果你用了Vuex的modules,要确保不同模块里的action/mutation没有同名冲突,或者没正确使用命名空间,导致调用混乱。
修正后的完整示例
你的store代码应该改成这样:
// store/index.js import axios from 'axios' export const state = () => ({ posts: [] }) export const mutations = { setPosts(state, posts) { state.posts = posts } } export const actions = { nuxtServerInit(vuexContext, context) { return axios .get("https://nuxt-blog.firebaseio.com/posts.json") .then(res => { const postsArray = []; for (const key in res.data) { postsArray.push({ ...res.data[key], id: key }); } vuexContext.commit("setPosts", postsArray); }) .catch(e => context.error(e)); } // 这里删掉了多余的setPosts action }
这样改完之后,再跑代码应该就不会出现栈溢出的问题了。如果还有问题,就再仔细检查有没有漏掉的循环触发点~
内容的提问来源于stack exchange,提问作者Ayman Tarig

