Vuex - получение состояния после мутации - PullRequest
0 голосов
/ 06 июня 2018

Я очень новичок в государственном управлении.В настоящее время я создаю список продуктов с бесконечными функциями загрузки.Это мои коды:

Это мой компонент:

<template>
  <div class="">
    <section class="space--sm">
      <div class="container">
          <div class="row">
              <div class="col-sm-12">
                    <div v-for="(data, index) in products" v-bind:key="data.id" class="item col-sm-4 col-xs-12" :id="'data-id-'+data.id" >
                        <a href="#" v-on:click.prevent="selectProduct(data)" >
                            <h4>{{data.name}}</h4>
                        </a>
                    </div>
                    <infinite-loading force-use-infinite-wrapper="true" @infinite="infiniteHandler" ref="infiniteLoading">
                        <span slot="no-results">
                            No results
                        </span>
                        <span slot="no-more">
                            There are no more results
                        </span>
                    </infinite-loading>
                </div>
          </div>
      </div>
    </section>
  </div>
</template>

<script>
import InfiniteLoading from 'vue-infinite-loading';
import { mapState, mapActions } from 'vuex';
export default {
    name: 'List',
    computed: mapState({
        products: state => state.list.products
    }),
    methods: {
        ...mapActions('list', [
            'selectProduct'
        ]),
        infiniteHandler($state) {
            setTimeout(() => {
                this.$store.dispatch('products/fetch')

                console.log(this.products.length); 
                //returns 0 but vue debugger says products state got datas

                if (this.products.length) {
                    $state.loaded();
                    if(this.products.length < 15){
                        $state.complete();
                    }
                } else {
                    $state.complete();
                }
            }, 1000);
        },
    },
    components: {
        InfiniteLoading
    }
}
</script>

Это мой магазин:

import axios from 'axios';

// initial state
const state = {
    products: [],
    selected_product: [],
    page: 1
}

// getters
const getters = {}

// mutations
const mutations = {
    FETCH(state, products) {
        state.products = state.products.concat(products);
    },
    selectProduct (state, { product }) {
        state.selected_product = product;
    },
    updatePage (state) {
        state.page += 1;
    },
}

// actions
const actions = {
    fetch({ commit }) {
        return axios.get('/api/get/products', {
            params: {
                page: state.page
            }
        })
        .then((response) => {
            commit('updatePage')
            commit('FETCH', response.data.data)
        })
        .catch();
    },
    selectProduct ({ state, commit }, product) {
        commit('selectProduct', { product })
    }
}

export default {
    namespaced: true,
    state,
    getters,
    actions,
    mutations
}

В методе infiniteHandler я сделал это:

this.$store.dispatch('products/fetch')

Состояние продуктов с более высокой мутацией должно было загружать данные внутри (проверено с помощью отладчика vue), но когда я делаю это после отправки: -

console.log(this.products.length);

Я получаю 0 , которыйтакже означает отсутствие данных внутри государства.Я делаю что-то не так?Также это лучшая практика использования Vuex?Спасибо

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Если асинхронное действие возвращает обещание (как и ваше), оно возвращается вызовом dispatch, поэтому ваш потребитель может ждать завершения действия.

Например,

async infiniteHandler($state) { // note, this is an "async" function
  setTimeout(() => {
    await this.$store.dispatch('products/fetch') // note the "await"

    console.log(this.products.length); 

    if (this.products.length) {
      $state.loaded();
      if(this.products.length < 15){
        $state.complete();
      }
    } else {
      $state.complete();
    }
  }, 1000);
},

Еще одна вещь, ваше catch() в конце действия fetch не окажет вам никакой пользы.Я бы посоветовал удалить его, чтобы ваши потребители могли быть осведомлены о любых ошибках.Это, или обработайте ошибку в вашем действии, но все же передайте отклонение обещания вашему компоненту, например,

.catch(res => {
  // handle error, maybe with your state
  throw res // make sure to keep rejecting the promise
})

и в вашем компоненте

try {
  await this.$store.dispatch('products/fetch') 
  // etc
} catch (e) {
  // do something else
}

Просто заметил еще одну вещь... вы должны использовать переданный в context state в ваших действиях, а не какой-то глобальный state объект, т.е.

fetch({ state, commit }) {
0 голосов
/ 07 июня 2018

this.$store.dispatch('products/fetch') является асинхронным.console.log(this.products.length); вызывается до завершения действия.

В этом случае следует использовать часы .

   watch: {
      products: function (newVal) {
        if (newVal.length) {
          $state.loaded();
          if(newVal.length < 15){
            $state.complete();
          }
        } else {
          $state.complete();
        }
      }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...