NuxtJS调用Firebase updateProfile更新用户photoURL时触发[vuex]状态修改错误
嘿,这个问题我之前也踩过坑!本质是Firebase的updateProfile方法会直接修改auth.currentUser对象的属性,而如果这个currentUser对象被你放到了Vuex的state里(或者通过Vuex的getter/响应式属性被组件引用),那这种直接修改就违反了Vuex的核心规则——只能在mutation handler里修改store的状态,所以触发了这个报错。
问题根源
当你调用updateProfile(auth.currentUser, { photoURL: ... })时,Firebase会直接更新auth.currentUser这个对象的photoURL属性。如果这个对象恰好是Vuex state的一部分(或者被Vuex的响应式系统追踪着),那这次修改就相当于在mutation之外直接操作了Vuex的状态,自然会被Vuex的校验机制拦截,抛出那个错误。
而你注释掉updateProfile后,只有setDoc操作Firestore的数据,没有触碰被Vuex追踪的对象,所以代码能正常运行。
解决方案:让Vuex来管理状态更新
正确的做法是:先让Firebase更新远程的用户数据,然后手动把最新的用户信息同步到Vuex的state里——而且必须通过Vuex的mutation来完成,不能直接修改state。
修改你的组件代码
async updateAvatar() { const auth = getAuth() try { // 1. 先调用Firebase的updateProfile更新远程的用户头像 await updateProfile(auth.currentUser, { photoURL: this.imageSrc.secure_url }) // 2. 重新加载用户信息,确保拿到最新的用户数据 await auth.currentUser.reload() // 3. 通过Vuex的mutation来更新本地state,这才符合Vuex的规则 this.$store.commit('user/updateUserPhoto', auth.currentUser.photoURL) // 4. 同步更新Firestore里的用户数据 await setDoc( doc(db, 'users', this.userProfile.uid), { avatar: { ...this.imageSrc } }, { merge: true } ) console.log('avatar updated!') } catch (error) { console.log(error) } }
在Vuex模块里添加对应的mutation
假设你的用户状态放在user模块里,在mutations中添加:
// store/user.js export const mutations = { updateUserPhoto(state, photoURL) { // 这里修改state里的用户头像,是Vuex允许的唯一方式 state.currentUser.photoURL = photoURL } }
额外提示
如果你不想通过mutation同步,也可以避免让Vuex直接追踪auth.currentUser对象——比如在获取用户信息时,把它转成一个普通的非响应式对象:
// 比如在Vuex的action里获取用户信息时 const user = Object.assign({}, auth.currentUser) // 或者用JSON序列化/反序列化来断开响应式连接 const user = JSON.parse(JSON.stringify(auth.currentUser)) // 再把这个普通对象放到state里
不过这种方式不推荐,因为可能导致本地状态和Firebase的用户数据不同步,还是通过mutation同步的方式更可靠。
内容的提问来源于stack exchange,提问作者redshift

