【问题标题】:Vue3/Vuex - Where am I "mutating vuex store state outside mutation handlers"?Vue3/Vuex - 我在哪里“在突变处理程序之外改变 vuex 存储状态”?
【发布时间】:2021-09-27 13:23:14
【问题描述】:

当调用 Firebase 成功更新的 Vuex Action,然后在 state.profile 上调用 Vuex Mutation 时,Vue 在 watch() 内的 save 上触发以下错误.

[Vue warn]: Unhandled error during execution of watcher callback

Error: [vuex] do not mutate vuex store state outside mutation handlers.

我已经克隆了store.state.profile,然后通过rfdcformData合并。

表单值在它自己的reactive() 数据对象formData 中更新,而不是立即提交存储以便稍后提供save()cancel() 选项。

模板

<template>
    <element-textarea
        id="about"
        title="About"
        :rows="10"
        v-model="about"
    ></element-textarea>
    <element-checkbox
        v-for="(specialty, i) in jSpecialties"
        :key="i"
        :id="specialty.toLowerCase()"
        :title="specialty"
        v-model="specialties[specialty]"
    >
        {{ specialty }}
    </element-checkbox>
</template>

脚本

...
const clone = require('rfdc/default')

export default defineComponent({
    ...
    setup(){
        ...
        let specialties: { [key: string]: boolean } = {}
        jSpecialties.map(name => (specialties[name] = false))
        const formData = reactive({
            about: '',
            specialties
        })

        watch(
            () => store.state.profile,
            () => {
                try {
                    Object.assign(formData, clone(store.state.profile))
                } catch (err) {
                    console.log('Error Appears Here', err)
                }
            }
        )

        const save = () =>
            store.dispatch('updateProfile', formData)
                .catch(err => console.log(err))

        return { ...toRefs(formData), save }
    }
})

vuex

export default createStore({
    strict: true,
    state: {
        profile: {}
    },
    mutations: {
        setProfile: (state, payload) => state.profile = payload,
    },
    actions: {
        updateProfile: ({state, commit}, data) => {
            const update = () =>
                db
                    .collection(...)
                    .doc(...)
                    .set(data, {merge: true})
                    .then(_ => commit('setProfile', data))
                    .catch(err => console.log(err))
            return update()
        }
    }
})

从 vuex 中删除 strict: true 时,我收到此错误:

Maximum recursive updates exceeded. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.


watch() 替换为watchEffect() 可以消除超出最大递归更新数 错误。

watchEffect(() => {
    try {
        Object.assign(formData, clone(store.state.profile))
    } catch (error) {
        console.log(error)
    }
})

但是,当使用 strict: true 更新 Vuex 时,我仍然收到以下信息:

Error: [vuex] do not mutate vuex store state outside mutation handlers.

【问题讨论】:

  • clone from rfdc 很可能不会剥夺您的store.state.profile 的反应性,clone(JSON.parse(JSON.stringify(store.state.profile))) 将确保反应性被剥夺
  • @Ohgodwhy 结果相同。
  • 我很确定你不能将 try..catch 块传递给 watch 函数的参数(或任何 JS 函数)
  • @Phil 结果是一个额外的Unhandled error during execution of watcher callback 错误。两个变成三个错误。
  • 我的意思是你的代码甚至不是有效的 JS。它应该生成 "Uncaught SytaxError: Unexpected token 'try'"。请参阅v3.vuejs.org/api/… 了解正确的语法

标签: javascript typescript vue.js vuejs3 vue-composition-api


【解决方案1】:

我发现了这个问题。我忽略了将引用对象复制回状态。

我需要在调度之前克隆 formData,因为同样的 data 对象也被提交通过操作存储。

const save = () =>
    store.dispatch('updateProfile', clone(formData))
        .catch(err => console.log(err))

【讨论】:

    猜你喜欢
    • 2019-09-24
    • 2019-11-30
    • 2018-02-13
    • 2022-01-09
    • 1970-01-01
    • 2020-03-30
    • 2023-03-09
    • 2016-11-16
    • 1970-01-01
    相关资源
    最近更新 更多