programing

Vuex - 변환 후 상태 가져오기

minecode 2023. 2. 3. 20:56
반응형

Vuex - 변환 후 상태 가져오기

나는 국가 경영에 매우 익숙하지 않다.저는 현재 무한 로딩 기능을 갖춘 제품 목록을 작성하고 있습니다.내 코드는 다음과 같습니다.

이것은 나의 컴포넌트입니다.

<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
}

infinite Handler 메서드에서는 다음과 같이 했습니다.

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

변환 제품 상태는 내부에 데이터를 로드해야 합니다(vue 디버거를 사용하여 확인). 그러나 디스패치 후 이 작업을 수행할 경우:-

console.log(this.products.length);

0이 됩니다.이것은, 주내에 데이터가 존재하지 않는 것을 의미합니다.제가 뭘 잘못했나요?또, 이것이 Vuex의 베스트 프랙티스입니까?감사해요.

비동기 액션이 약속을 반환하는 경우(사용자의 약속과 같이) 콜에 의해 반환됩니다.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()페치액션이 끝날 때쯤엔 아무 도움이 되지 않을 거야당신의 소비자들이 오류를 알 수 있도록 그것을 제거하는 것이 좋습니다.또는 액션의 오류를 처리하면서도 약속 거부를 컴포넌트에 전달합니다.

.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
}

방금 또 다른 걸 알아챘는데...전달된 컨텍스트를 사용해야 합니다. state당신의 행동에서, 일부 글로벌한 것이 아니라state오브젝트, 즉

fetch({ state, commit }) {

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();
        }
      }
    }
async infiniteHandler($state) { 
  setTimeout(() => {
    await this.$store.dispatch('products/fetch') 

    console.log(this.products.length); 

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

언급URL : https://stackoverflow.com/questions/50729383/vuex-getting-state-after-mutation

반응형