Состояние доступа 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-это все о наблюдении за состоянием и управлении, так как я могу предотвратить эту ошибку консоли?



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

535   3  

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"

Comments

    Ничего не найдено.