等待后Vuex提交不会更新状态

时间:2020-04-29 14:19:21

标签: javascript vue.js async-await vuex

在这里和其他地方,我已经阅读过多个类似的问题,但我无法弄清楚。

我有一个带有mapGetters的表单,其输入值应根据Vuex状态进行更新:

    ...mapGetters({
      show: "getShow"
    }),

示例表单输入(我正在使用Bootstrap Vue)

      <b-form-input
        id="runtime"
        name="runtime"
        type="text"
        size="sm"
        v-model="show.runtime"
        placeholder="Runtime"
      ></b-form-input>

然后在表单组件上有此方法:

    async searchOnDB() {
      var showId = this.show.showId;
      if (!showId) {
        alert("Please enter a showId");
        return;
      }
      try {
        await this.$store.dispatch("searchShowOnDB", showId);
      } catch (ex) {
        console.log(ex);
        alert("error searching on DB");
      }
    },

以及此商店上的操作:

    async searchShowOnDB({ commit, rootState }, showId) {
      var response = await SearchAPI.searchShowOnDB(showId);
      var show = {
        show_start: response.data.data.first_aired,
        runtime: response.data.data.runtime,
        description: response.data.data.overview
      };
      //I'm updating the object since it could already contain something
      var new_show = Object.assign(rootState.shows.show, show);
      commit("setShow", new_show);
    }

变异:

    setShow(state, show) {
      Vue.set(state, "show", show);
    }

searchAPI:

export default {
    searchShowOnDB: function (showId) {
        return axios.get('/search/?id=' + showId);
    },
}

一切正常,API调用已执行,我什至可以在Vue Devtools中看到Vuex更新状态,但是表单未更新。 一旦我在输入字段中输入内容或在Vue Devtools中点击commit,表单字段show_startruntimedescription就会全部更新。

此外,它可以正常工作并更新所有内容:

    async searchShowOnDB({ commit, rootState }, showId) {
      var show = {
        show_start: "2010-03-12",
        runtime: 60,
        description: "something"
      };
      //I'm updating the object since it could already contain something
      var new_show = Object.assign(rootState.shows.show, show);
      commit("setShow", new_show);
    }

我不知道该怎么办,我尝试了明确地解决Promises的尝试,删除了async / await并使用axios.get(...).then(...),四处移动...似乎无济于事。

2 个答案:

答案 0 :(得分:1)

15的第/modules/search.js行上,您正在Object.assign()上使用rootState.search.show。这会使search的{​​{1}}属性发生突变(顺便说一句, 您应该只对内部突变进行突变 !)。在下面阅读原因。

然后您尝试触发突变。但猜猜怎么了? Vue看到它是相同的值,因此没有组件被通知,因为没有更改。这就是为什么您应该 从不 在突变之外进行突变!

因此,不要将值分配给操作中的状态,只需提交新的显示(用以下内容替换行state

15-16

在此处查看:https://codesandbox.io/s/sharp-hooks-kplp7?file=/src/modules/search.js

这会将 commit('setShow', show); 完全替换为state.show。如果您只想将响应合并到当前show中(以保留添加到当前state.show中的一些自定义内容),则可以传播show的内容并用{{ 1}}:

state.show

还请注意,您的突变不需要show。您在任何突变的第一个参数中都具有commit("setShow", { ...rootState.search.show, ...show }); ,这就是当前模块的Vue.set()。因此,只需分配state

最后一点:当vuex变大时,您可能希望namespace模块,以避免任何名称冲突。

答案 1 :(得分:0)

在模板中使用的状态下,对象的所有道具都必须存在,或者应该为此类属性调用Vue.set。

  state: {
    show: {
      runtime: null // <- add this line
    }
  },

您为整个对象调用Vue.set,但是它已经存在于状态中,并且您没有用新的替换它,而只是替换了props。在您的情况下,您有一个空对象,并使用Object.assign添加“运行时”属性。 同样,所有带有状态的操作都应在突变中完成

      var new_show = {
        runtime: response.data.url
      };
      commit("setShow", new_show);
...
  mutations: {
    setShow(state, new_show) {
      Object.assign(state.show, new_show)
    }
  },