Programing

Vuex 글로벌 상태 변경이 Nuxt의 v-for 루프에서 리렌더 구성 요소를 트리거하지 않음

c10106 2022. 5. 24. 22:52
반응형

Vuex 글로벌 상태 변경이 Nuxt의 v-for 루프에서 리렌더 구성 요소를 트리거하지 않음

나는 Vue.js에서 아동 구성 요소 리렌더와 함께 vuex 글로벌 상태 조합을 사용하는 것이 어렵다.글로벌 상태는 변이되지만 데이터를 v-for 루프에서 다시 렌더링하지 않는다.

모든 데이터 목록이 렌더링되지만, 새로운 데이터가 변경될 때 /blog의 구성요소는 데이터의 데이터를 변경하지 않는다.

몇 가지 코드:

/store/index.js

export const state = () => ({
  allData: [],
})
export const getters = {
  getAllData: (state) => state.allData,
}
export const mutations = {
  GET_DATAS(state, payload) {
    state.allData = payload
  },
  UPDATE_DATA(state, payload) {
    const item = state.allData[payload.index]
    Object.assign(item, payload)
  },
}
export const actions = {
  getDatas({ commit, state }, payload) {
    return fetch(`URL_FETCH`)
      .then((data) => data.json())
      .then((data) => {
        commit('GET_DATAS', data)
      })
      .catch((err) => console.log(err))
  },
  updateData({ commit, state }, payload) {
    commit('UPDATE_DATA', payload)
  },
}

/layouts/default.vue

beforeCreate() {
  this.$store.dispatch('getDatas').then(() => {
    connectSocket()
  })
},
methods: {
  connectSocket() {
    // connect & received message from socket
    // received message from socket
    this.$root.$emit('updateData', {
      index: 12,
      price: 34,
      change: 56,
      percent: 78,
    })
  },
},

/pages/blog/index.vue

<template>
  <div>
    <div
      v-for="index in getAllData"
      :key="index.name"
      class="w-100 grid-wrapper"
    >
      <div>{{ index.price }}</div>
      <div>{{ index.change }}</div>
      <div>{{ index.percent }}</div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    ...mapGetters(['getAllData']),
  },
  mounted() {
    this.$root.$on('updateData', (item) => {
      this.$store.dispatch('updateData', {
        index: item.index,
        price: item.price,
        percent: item.percent,
        change: item.change,
      })
    })
  },
}
</script>

다음은 Vuex를 사용하고 데이터를 Nuxt 앱에 효율적으로 로드하는 방법에 대한 전체 예(주관적이지만 모범 사례를 사용함)이다.

/pages/index.vue

<template>
  <div>
    <main v-if="!$fetchState.pending">
      <div v-for="user in allData" :key="user.id" style="padding: 0.5rem 0">
        <span>{{ user.email }}</span>
      </div>
    </main>
    <button @click="fakeUpdate">Update the 2nd user</button>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  data() {
    return {
      mockedData: {
        name: 'John Doe',
        username: 'jodoe',
        email: 'yoloswag@gmail.com',
        phone: '1-770-736-8031 x56442',
        website: 'hildegard.org',
      },
    }
  },
  async fetch() {
    await this.setAllData()
  },
  computed: {
    ...mapState(['allData']),
  },
  methods: {
    ...mapActions(['setAllData', 'updateData']),

    fakeUpdate() {
      this.updateData({ index: 1, payload: this.mockedData })
    },
  },
}
</script>

/store/index.js

import Vue from 'vue'

export const state = () => ({
  allData: [],
})

export const mutations = {
  SET_ALL_DATA(state, payload) {
    state.allData = payload
  },
  UPDATE_SPECIFIC_DATA(state, { index, payload }) {
    Vue.set(state.allData, index, payload)
  },
}

export const actions = {
  async setAllData({ commit }) {
    try {
      const httpCall = await fetch('https://jsonplaceholder.typicode.com/users')
      const response = await httpCall.json()
      commit('SET_ALL_DATA', response)
    } catch (e) {
      console.warn('error >>', e)
    }
  },
  updateData({ commit }, { index, payload }) {
    commit('UPDATE_SPECIFIC_DATA', { index, payload })
  },
}

참조URL: https://stackoverflow.com/questions/70362331/vuex-global-state-change-does-not-trigger-re-render-component-in-v-for-loop-in-n

반응형