jiwoolee.space

Vuex helpers로 api 호출하기 본문

Frontend-Vuejs

Vuex helpers로 api 호출하기

jiwoolee 2021. 8. 4. 10:04

Helpers ( mapState, mapGetters, mapMutations, mapActions) 를 배웠으니 써야지

 

일단 만들어두었던 template를 다시 보자

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th colspan="2">DB info 보기</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>UserID</td>
          <td>Country</td>
        </tr>

	===================여기 이부분===================
        <tr v-for="i in this.UserID.length" v-bind:key="i">
          <td>{{ UserID[i - 1] }}</td>
          <td>{{ Country[i - 1] }}</td>
        </tr>
        ===================여기 이부분===================
        
      </tbody>
    </table>
  </div>
</template>

코드셀에 표시해둔 부분을 고쳐야겠네

 

 

 

 

 

 

 

script를 만들어보자

우선,

mapGetters, mapActions를 쓸 거니까 import부터 해주자

//myTable.vue

import {mapGetters} form "vuex"
import {mapActions} form "vuex"

 

**

mapState, mapMutations는 안써줘도 된다 

=> frontend에서 mapActions로 api를 불러오고 mapGetters로 데이터를 불러와서 꼭 써줘야 하는데,

=> frontend에서 쓰지 않는 mapState, mapMutations는 써주지 않아도 된다

 

 

 

 

 

 

 

 

다음, src/store/store.js를 써주자

//모듈을 조합하고 저장소를 내보내는 곳
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";


Vue.use(Vuex)

기본으로 사용할 vue, vuex, axios를 import해주고

Vue.use(Vuex) 로 vuex를 사용하기 위해 vue에 등록해주어야 한다

 

 

 

 

 

 

 

 

이어서,

export default new Vuex.Store()를 채워주자

 

첫번째로, state.

state는 view와 직접적으로 연결되어 있는 model이지

state에 상태를 저장할 DBdata라는 object를 생성해주고 초기 기본값을 공백으로 주자

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


Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //view와 직접적으로 연결되어 있는 model
    DBdata: {}
    //상태를 저장할 data object 생성 + 기본값 공백
  },
}

 

왜 object를 만들어주냐면,

지난 시간에 확인했던 데이터의 형태를 보자

object 형태다

 

 

 

 

 

 

 

 

다음으로는 api를 호출해야겠지

API 서버 통신과 같은 역할을 수행하는 메소드는 actions다

보통 state에 반영하기 전에

  • 데이터를 조회하고
  • 데이터를 가공하는 역할을 한다
actions:{
async fetchSignUpInfos({commit}) {
	try{
        const {data} = await axios.get(
        "http://localhost:4003/api/v1/infos/get"
                );
                commit("FETCH_SIGNUPINFOS_mutations",data)
     	}
    catch(error){
        console.log(error);
        }
        
 }
 }

axios를 이용해 object 중 data를 api 호출하고,

commit을 이용해,

mutations의 FETCH_SIGNUPINFOS_mutations 호출해 data를 보내주려고 한다.

 

 

 

 

 

 

 

 

 

 

 

그러면,

mutations의 FETCH_SIGNUPINFOS_mutations도 써줘야겠지

mutations는 state를 변경하는 유일한 메서드다

 

mutations: {
	FETCH_SIGNUPINFOS_mutations(state,data) {
	return state.Dbdata=data
                            }

 

FETCH_SIGNUPINFOS_mutations로

state의 DBdata가 actions에서 받아온 data가 되도록 해준다.

 

 

 

 

 

 

 

 

 

 

마지막으로 getters도 써주자

  getters: {
    //Vue 컴포넌트에서 Computed 의미
    getData(state) {
      console.log(state.DBdata)
      return state.DBdata
    }
  },

 

 

 

 

 

 

 

 

 

전체 store.js를 보자면 이렇다

//모듈을 조합하고 저장소를 내보내는 곳
import Vue from 'vue'
import Vuex from 'vuex'
import axios from "axios";


Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    DBdata: {}
  },

  getters: {
    getData(state) {
      console.log(state.DBdata)
      return state.DBdata
    }
  },

  mutations: {
    FETCH_SIGNUPINFOS_mutations(state, data) {
      console.log("FETCH_SIGNUP_OBJECT DONE")
      return state.DBdata = data
    }

  },

  actions: {
    async fetchSignUpInfos({ commit }) {
      try {
        const { data } = await axios.get(
          "http://localhost:4003/api/v1/infos/get"
        );
        console.log("fetchSignUpInfos DONE")
        console.log(data)
        commit('FETCH_SIGNUPINFOS_mutations', data)
      }
      catch (error) {
        console.log(error);
      }
    }

  }
})

 

 

 

 

 

 

 

 

 

 

이제 store.js를 다 작성했으니 

myTable.vue에서 script도 마저 써주자

import { mapGetters } from "vuex";
import { mapActions } from "vuex";

export default {
  name: "myTable",
  data() {
    return {};
  },

위에서 써둔 script에 이어서

name: "myTable" 를 써주고

data()도 추가해주자

 

 

 

 

 

 

 

 

 

 

 

다음으로 

mapGetters, mapActions를 써주자

computed: {
    ...mapGetters({ DBdata: "getData" }),
  },

  methods: {
    ...mapActions([
      "fetchSignUpInfos",
      //this.fetchSignUpInfos()을
      //this.$store.dispatch('fetchSignUpInfos')에 매핑
    ]),
  },

 

 

왜 mapGetters랑 mapActions를 같은 computed나 methods에 써주지 않았을까

=> component에서 헬퍼를 이용해서 state, getters, mutations, actions를 가져올 때 위치를 꼭 지켜야 하기 때문이다

=> mapState와 mapGetters는 computed 안에 들어가야 되고,

=> mapMutations와 mapActions는 methods안에 있어야 한다

 

 

 

 

 

 

 

 

 

다음으로 mounted.

mounted() {
    this.fetchSignUpInfos();
  },

fetchSignUpInfos를 mounted 해주는 이유는

........뭐라고 써야 할까

(미리 데이터를 조회하려고?)

 

 

 

 

 

 

 

 

 

script도 다 썼다

최종 script는 이렇게 생겼다


<script>
import { mapGetters } from "vuex";
import { mapActions } from "vuex";

export default {
  name: "myTable",
  data() {
    return {};
  },

  mounted() {
    this.fetchSignUpInfos();
  },

  computed: {
    ...mapGetters({ DBdata: "getData" }),
  },

  methods: {
    ...mapActions([
      "fetchSignUpInfos",
    ]),
  },
};
</script>

 

 

 

 

 

 

 

 

 

정말 마지막이다

	===================여기 이부분===================
        <tr v-for="i in this.UserID.length" v-bind:key="i">
          <td>{{ UserID[i - 1] }}</td>
          <td>{{ Country[i - 1] }}</td>
        </tr>
        ===================여기 이부분===================

template에서 이 부분만 고쳐주자

 

  <tr v-for="i in this.DBdata" v-bind:key="i">
          <td>{{ i.UserID }}</td>
          <td>{{ i.Country }}</td>
</tr>

DBdata의 첫번째 UserID, Country, 두번째 UserID, Country,  ....가 들어갈 수 있도록 써주었다

 

 

 

 

 

 

최종 myTable.vue는 이렇게 생겼다.

<template>
  <div>
    <table>
      <thead>
        <tr>
          <th colspan="2">DB info 보기</th>
        </tr>
      </thead>

      <tbody>
        <tr>
          <td>UserID</td>
          <td>Country</td>
        </tr>

        <tr v-for="i in this.DBdata" v-bind:key="i">
          <td>{{ i.UserID }}</td>
          <td>{{ i.Country }}</td>
        </tr>
        
      </tbody>
    </table>
  </div>
</template>




<script>
import { mapGetters } from "vuex";
import { mapActions } from "vuex";

export default {
  name: "myTable",
  data() {
    return {};
  },

  mounted() {
    this.fetchSignUpInfos();
  },

  computed: {
    ...mapGetters({ DBdata: "getData" }),
  },

  methods: {
    ...mapActions([
      "fetchSignUpInfos",
    ]),
  },

};
</script>

<style>
table,
td {
  border: 1px solid #333;
}
thead,
tfoot {
  background-color: #333;
  color: #fff;
}
</style>

 

 

 

 

 

 

 

 

 

 

server를 확인할 수 있겠다

데이터가 아주 잘 들어갔다

 

 

 

 

 


 

 

**

F12로 콘솔창을 확인해보니

2가지 warn이 있다

warn:

[Vue warn]: Avoid using non-primitive value as key, use string/number value instead.

[Vue warn]: Duplicate keys detected: '[object Object]'. This may cause an update error.

=> v-for 사용하실 때 v-bind:key에 문자열이랑 숫자만 넣어야 해서 나는 오류라고 한다

=> 나는 :key="i"라고 했으니

=> i.DBdata 로 고쳐주었다

 

Warn 모두 해결!