본문 바로가기
Front-End (web)/Vue.js Typescript

[Vue.js/Typescript] 8. Axios, Mutation, Action

by 햄과함께 2019. 8. 15.
320x100

이번에는 Api 통신으로 Vuex의 State 값을 갱신하는 것까지 해보자.

Api 통신은 https://reqres.in 요 사이트를 이용한다.


Axios

$ npm install --save-dev axios

Axios 설치 & 의존성 추가.

 

reqres 사이트에서 제공하는 api중 위 API를 사용해보자.

// src/types/user.ts
export interface UserResponse {
    data: User;
}

export interface User {
    id: number;
    email: string;
    first_name: string;
    last_name: string;
    avatar: string;
}

응답값을 보고 응답값에 맞는 인터페이스를 만든다.

 

// src/api/reqres.ts
import axios, { AxiosPromise } from 'axios';
import { UserResponse } from '@/types/user';

// reqres 사이트와 통신에 사용할 axios 객체 하나만들어두고 재사용하기
const reqresApi = axios.create({
    baseURL: 'https://reqres.in', // Url
    timeout: 5000 // timeout 5초
});

// userId를 파라미터로 받아서 API 통신으로 user 데이터 가져오기
export function fetchUser(id: number): AxiosPromise<UserResponse> {
    return reqresApi.get(`/api/users/${id}`);
}

API request는  /api/users/{userId} 이다.

Axios는 axios.get 으로 바로 사용할수 있지만 url이나 header, timeout 등 재사용될 설정들이 중복될 경우를 대비하여 axios.create 로 미리 설정들을 세팅해서 사용했다.

다른 컴포넌트에서는 fetchUser 함수를 임포트해서 사용하면 api 통신 결과를 받아올 수 있다.


// src/store/modules/reqres.ts

import { User, UserResponse } from '@/types/user';

export const namespaced = true;

interface State {
    user: User | null;
}

// user 데이터를 가지고 있는 Reqres 모듈
export const state: State = {
    user: null
}

일단 user데이터를 가지고 있는 Vuex 모듈을 하나 만든다.

default는 null로 설정했다.

 

Vuex의 state는 많은 컴포넌트에서 접근이 가능하기 때문에 관리를 위해 다이렉트로 갱신이 불가능하다.

 this.$store.state.reqres.user = new User(); 

위와 같이 다이렉트로 갱신하면 안됨.

 

Vuex는 단방향 데이터 흐름을 가진다.

State를 수정할 수 있는 방법은 Mutation, Action이 있다.

Mutation은 동기적으로 state를 변경시키고자 할 때 사용한다.

Action은 비동기적으로 state를 변경시키고자 할 때 사용한다.


Mutation

앞서 말했듯이 Mutation은 state를 동기적으로 변경시킬 때 사용한다. 

 

// src/store/modules/reqres.ts

// add mutation
export const mutations = {
    // state의 user를 파라미터로 받아온 데이터로 갱신 
    SET_USER(state: State, user: User): void {
        state.user = user;
    }
}

SET_USER mutation 함수는 user라는 파라미터를 받아서 state의 user를 갱신한다.

 this.$store. commit ('reqres/SET_USER') 으로도 호출할 수 있다.


Action

Action은 state를 비동기적으로 변경시킨다.

비동기적으로 동작하는 외부 통신 같은 경우는 Action을 사용한다.

// src/store/modules/reqres.ts

// add
import { fetchUser } from '../../api/reqres';
import { AxiosResponse } from 'axios';

// add
export const actions = {
    async fetchUser({ commit }: any, id: number) { // id를 받는다.
        console.log('call fetchUser');
        await fetchUser(id) // api 통신
            .then((response: AxiosResponse<UserResponse>) => {
                const user: User = response.data.data;
                console.log(user);
                commit('SET_USER', user); // mutation 으로 state 갱신
            })
            .catch((e: Error) => { throw e; })
    }
};

action 함수는 위와 같다.

코드를 보면 알다시피 state 값을 갱신하기 위해 결국은 mutation 함수를 호출한다.

즉, Action -> Mutation -> State 갱신 순이다. (단방향 데이터 흐름)

Action은 this.$store. dispatch ('reqres/fetchUser') 로도 호출할 수 있다. 


fetchUser action을 호출하는 Component 추가.

// src/components/Reqres.vue

<template>
  <div>
    <h1>User Data</h1>
    
    // user가 있다면 -> 정보 출력
    <div v-if="user != null">
      id : {{ user.id }}<br>
      email : {{ user.email }}<br>
      first_name : {{ user.first_name }}<br>
      last_name : {{ user.last_name }}<br>
      avatar : {{ user.avatar }}<br>
    </div>
    
    // user가 없는 경우
    <div v-else>
      user is Null
    </div>
    
    // /api/users/2 api 통신
    <button @click="fetchUser(2)">
      action 호출
    </button>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
import { mapActions } from 'vuex';
import { State } from 'vuex-class';
import { User } from '@/types/user';

@Component({
    methods: {
    ...mapActions('reqres', ['fetchUser']) // action 가져오기
    }
})
export default class Reqres extends Vue {
    @State('user', {namespace: 'reqres'})
    private user!: User
}
</script>

확인용 컴포넌트를 위와 같이 만들었다.

버튼을 클릭할 때  action  ->  axios (api 통신) --성공-->  action  ->  mutation  ->  state  (user update) 흐름으로 user가 갱신된다.

 

결과

처음에는 왼쪽과 같이 "user is Null" 이 출력되고 "action 호출" 버튼을 누르면 데이터를 받아와서 오른쪽과 같이 화면에 뿌려준다.


참고 깃허브 : add Axios, Mutation, Actions


참고 : [Vue.js Guide] 변이, 액션

320x100

댓글