【Vue/Nuxt】-Vuex編- 天気APIを使って一通りフロントを実装してみる

## はじめに
天気APIを例に、自分が理解しにくかったVuex・テスト（jest）をメインに解説したいと思います。

単体の記事（Vuexだけとか）は良いものがたくさんあるので、一通り実装すると、こんなコードになるよー。というサンプル感を意識しました👍

## 環境
- nuxt : 2.0.0
- @vue/test-utils: 1.0.0-beta.26
- vue-jest : 3.0.0
- vuex-map-fields : 1.3.1
- lodash : 4.17.11
- axios : 0.18.0

## 目指すところ

- livedoorのお天気WebサービスAPI「Weather Hacks」を使って天気を取得
（http://weather.livedoor.com/weather_hacks/webservice ）

- 取得したデータをストア（Vuex）で管理
- 「今日」「晴れのち雨」「画像」部分をコンポーネント化する
- コンポーネントとストアのテストを書く

見た目はこんな感じ
<img width="549" alt="スクリーンショット 2019-03-12 22.33.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/239038/7e885431-b3eb-1025-2876-95fb0cf2b1ee.png">

## ①天気APIのレスポンスをコンソールに出す

まずは画面を構成するレスポンスをコンソールに出し、
そこから画面を作っていくのが個人的に好きなので、ストアを書きます！

### 天気データを管理するストアを作成

```store.js
import Vue from 'vue';
import { getField } from 'vuex-map-fields';
import axios from 'axios';

const actionsPayload = {};
const mutationsPayload = {};
const actions = {};
const mutations = {};

const getters = {
  getField
};

const state = () => ({
  weather: null
});

actionsPayload.fetchWeather = {
  weather: {
    type: Object
  }
};
actions.fetchWeather = async (store) => {
  const res = await axios.get(`http://weather.livedoor.com/forecast/webservice/json/v1?city=400040`).catch((err) => {
    throw new Error(err);
  });

  // レスポンスがコンソールに表示されるかなドキドキ
  console.log(res);

  store.commit('updateWeather', { weather: res });
};
mutationsPayload.updateWeather = {
  weather: {
    type: Object,
    required: true
  }
};
mutations.updateWeather = (state, payload) => {
  Vue.set(state, 'weather', payload.weather);
};

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

```

Vuexまだ理解しきれてない人は、この記事がおすすめなので見て🙌
[vuexをまだ理解していない全人類に捧ぐvuexを利用したコードの図解](https://qiita.com/fruitriin/items/42b0ebc5f8a524a0ae17)

実際にデータを取得しているのは `axios.get('http://weather.livedoor.com/forecast/webservice/json/v1?city=400040')` の部分。
（city=400040はWeather Hacksの福岡県久留米のID）

定数 `res` に代入し、console.logしています。
actionsを実行するには、Vueインスタンス側からストアを参照してdispatchをしないといけないので、ファイルを作りましょう〜

### Pagesにファイルを作る
参考：[ディレクトリ構造 - Nuxt.js](https://ja.nuxtjs.org/guide/directory-structure/#pages-%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA)

```index.vue
<template>
  <section class="weather">
    天気
  </section>
</template>

<script>
import { mapFields } from 'vuex-map-fields';

export default {
  computed: {
    ...mapFields('weatherApp', ['weather'])
  },
  async asyncData({ store, params }) {
    await store.dispatch('weatherApp/fetchWeather');
  }
};
</script>
```

大事なのは `store.dispatch('weatherApp/fetchWeather');` ！！
weatherAppストアのfetchWeatherを実行してね、という意味。

ちなみに、mapFieldsを使うと、weatherAppストアのweatherだけを取ってこれるので便利です🎉
参考：[maoberlehner/vuex-map-fields: Enable two-way data binding for form fields saved in a Vuex store](https://github.com/maoberlehner/vuex-map-fields)

これでブラウザを確認してみると。。

<img width="727" alt="スクリーンショット 2019-03-12 23.13.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/239038/37691241-58a5-3828-8b94-7e1847284f15.png">
**キタ！！ちゃんとレスポンスが取れました**

次の記事ではレスポンスを表示させていきます〜
[【Vue/Nuxt】-コンポーネント編- 天気APIを使って一通りフロントを実装してみる](https://qiita.com/kawa64372358/items/fd7d2cf4234470dc94a5)