stateを直接参照しないシンプルなVuexサイクル


Vuexとは?

Vue.jsアプリケーションにおける状態管理パターンライブラリです。

コンポーネント間のデータや関数の受け渡しには、propsやemitを使いますが、Vuexは全てのコンポーネントのための集中型のStoreになります。
propsやemitだけでデータの受け渡しをするのは、バケツリレーに似ていて、vueファイルに何度も同じコードを書く必要があったり、無駄にロジックが発生します。

Vueコンポーネント層とVuexはどう繋がるのか?

今回の記事のタイトルは「stateを直接参照しないシンプルなVuexサイクル」です。
Vueコンポーネント層からStore内のstateにアクセスするためには

  • store.statemapStateを使ってstateを直接する方法
  • store.gettersmapGettersを用いて、取得する方法

があります。

ただ、Stateの変更をどこからでも直接、自由に変更、取得可能だと、全コンポーネント共通で参照可能なStateの秩序を保つことが出来ません。
そのため、公式ドキュメントにも掲載されている以下の図の通り、VuexのライフサイクルをルールとしてStateを変更、取得します。

stateの変更はMutationsが行い、vueコンポーネント層からはgetterを使用してStateの値を取得します。
そのMutaitionsはVueコンポーネント層から呼ばれるActionsによって実行されます

話がややこしくなってきたのでもう少し詳細にしてみます。
Vue.jsやNuxt.jsとVuexを使ってStateを管理したい。
そんなときに登場してくるのは Actions Mutaitions State Getters この4つです。

Vuex それぞれの役割

今回は、Firestoreに保存されているItemsを取得し、それをVuexのStateに格納して、コンポーネント層で使用する例を挙げます。
store/items以下に
- state.js
- action.js
- mutaition.js
- getter.js

を準備します。

State

Stateでは初期値を格納します。
基本的には配列が入る想定であれば[]、文字列を想定すれば''を初期値にします。
state.jsを用意して以下のように記述すると

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

stateの初期値はから配列になります。

Getters

GettersではStateの値をコンポーネント層で取得する際に使います。
例えば、Stateに格納されているallItemsを取得するなら以下のようにして

export const getters = {
  getAllItems: state => state. allItems
}

vueコンポーネントからは

computed: {
  allItems() {
    return this.$store.getters['items/getAllItems']
  }
}

のようにして取得できます。

ただこのままだと、allItemsは空配列なのでMutaitionsからStateを更新します。

Mutations

Actionsを定義する前に、Mutationsを用意します。

export const mutations = () => {
  setAllItems(state, items) {
    state.allItems = items
  }
}

setAllItemsという関数を作ります。
第1引数は値を変更するstateで、第2引数はActionsからもらうitemsとなります。
そのitemsをStateのallItemsの代入することでStateを更新できます。

Actions

次にVueコンポーネント層からActionsを呼ぶ必要があるので定義します。

export const actions = () => {
  async fetch({ commit }) {
    const docs = await Firestore.collection('items').get()
    const items = docs.map(doc => doc.data())
    commit('setAllItems', items)
  },
}

commit関数の第1引数にMutaitionsの実行したい関数を文字列で指定し、第2引数にFirestoreから取得したitemsを指定します。

コンポーネント層でからは以下のようにActionsを呼ぶことが出来ます。

fetch({store}) {
  store.dispatch('items/fetchAllItems')
}

所感

今回はState Getters Mutations Actionsの順で実装しましたが、どこから実装するのかに問題はありません。
名称からどんな役割があってどこからどんなふうに呼び出せば良いのか覚えるまでに時間がかかるかもしれませんが、使っていくうちに分かってきます。

ちなみにmentaというコーチングサービスでVue.jsを中心にメンターをしています。
もう少し詳しい内容を聞きたい方や、Vue.jsの勉強に行き詰まっている方など、ぜひmentawatsuyo_2にメッセージをしてください!

参考

Vuex とは何か?