Состояние доступа Vuex до завершения асинхронного действия


У меня возникли проблемы, когда вычисляемый геттер обращается к состоянию до его обновления, таким образом, представляя старое состояние. Я уже пробовал некоторые вещи, такие как слияние мутаций с действиями и изменение состояния на множество различных значений, но геттер все еще вызывается до завершения отправки.

Задача

Состояние вызывается до завершения асинхронного действия (вызова api).

Структура кода

  1. компонент a загружает API данные.
  2. пользователь нажимает 1 из данных.
  3. компонент А отправляет щелкнутые данные (объект) компоненту В.
  4. компонент B загружает полученный объект.

Примечание

DOM делает прекрасно. Это ошибка консоли. Вью всегда следит за тем, чтобы дом менялся и перерисовывался мгновенно. Консоль, однако, забирает все.

Цель

Запретить компоненту B (который вызывается только после компонента) запускать его вычисляемый метод геттера до завершения отправки компонента а.

Магазин.js

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios';

Vue.use(Vuex);

export const store = new Vuex.Store({

  state: {
    searchResult: {},
    selected: null,
  },

  getters: {
    searchResult: state => {
      return state.searchResult;
    },
    selected: state => {
      return state.selected;
    },
  },

  mutations:{
    search: (state, payload) => {
      state.searchResult = payload;
    },
    selected: (state, payload) => {
      state.selected = payload;
    },
  },

  actions: {
    search: ({commit}) => {
      axios.get('http://api.tvmaze.com/search/shows?q=batman')
        .then(response => {
          commit('search', response.data);
        }, error => {
          console.log(error);
        });
    },

    selected: ({commit}, payload) => {
      commit('selected', payload);
    },
  },

});

Результат поиска.vue

<template>
<div>
  //looped
  <router-link to="ShowDetails" @click.native="selected(Object)"> 
      <p>{{Object}}</p>
  </router-link>
</div>
</template>

<script>
export default {
  methods: {
    selected(show){
      this.$store.dispatch('selected', show);
    },
  },
}
</script>

ShowDetails.vue

<template>
<div>
  <p>{{Object.name}}</p>
  <p>{{Object.genres}}</p>
</div>
</template>

<script>
export default {
  computed:{
    show(){
      return this.$store.getters.selected;
    },
  },
}
</script>

Это изображение показывает, что вычисляемый метод " show "в файле 'ShowDetails' выполняется до обновления состояния (что происходит до вычисляемого метода" show"). Затем, после обновления, вы можете увидеть 2-ю консоль "TEST", которая теперь фактически заполнена объектом, через несколько мс после первой консоли"TEST".

Вопрос

Vuex-это все о наблюдении за состоянием и управлении, так как я могу предотвратить эту ошибку консоли?

Заранее благодарю.

3   2   2017-06-20 09:09:30

3 ответа:

store.dispatch может обрабатывать обещание, возвращаемое обработчиком инициированного действия, и он также возвращает обещание. См. Составление Действий.

Вы можете настроить ваше выбранное действие, чтобы вернуть обещание следующим образом:

selected: ({commit}, payload) => {
    return new Promise((resolve, reject) => {
        commit('selected', payload);
    });
} 

Затем в результатах поиска .vue вместо использования router-link используйте кнопку и выполните программную навигацию в успешном обратном вызове вашего выбранного обещания действия следующим образом:

<template>
<div>
  //looped
  <button @click.native="selected(Object)"> 
      <p>{{Object}}</p>
  </button>
</div>
</template>

<script>
export default {
  methods: {
    selected(show){
      this.$store.dispatch('selected', show)
          .then(() => {
            this.$router.push('ShowDetails');
        });
    },
  },
}
</script> 

Инициализируйте свои состояния. Как и со всеми другими данными Vue, всегда лучше инициализировать его в начальной точке, даже с пустыми '' или [], но VueJS (не уверен, что Angular или React действуют одинаково, но я предполагаю, что они похожи) будет вести себя намного лучше, когда все ваши переменные инициализированы.

Вы можете определить начальное пустое значение ваших состояний в экземпляре магазина.

Вы найдете это полезным не только здесь, но, например, с проверкой форм, так как большинство плагинов будет работать нормально. инициализированные данные, но не будет работать должным образом с неинициализированными данными.

Надеюсь, это поможет.

Вы можете попробовать использовать v-if, чтобы избежать рендеринга шаблона, если это не Результаты поиска

v-if="$store.getters.searchResult"