241
167

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

VuexのMutationとActionの切り分け

Last updated at Posted at 2017-10-05

Vuexを勉強してたらMutationとActionで処理の切り分けをどうしようか、というところで悩んだので自分なりの考えを書きます。

MutationとActionの違い

そもそもMutationは同期処理でなければならなず、Actionは非同期処理も可能という違いがあります。
これは、Mutationで複数の状態の変更が非同期に行われた場合に挙動が予測不能になるのを防ぐという意図があるようです。
Actionでは、Mutationに対してcommitを行うことで間接的に状態を変更しますが、Actionを呼び出すためのdispatchメソッドはPromiseを返すため、処理の順序を制御することが可能になります。

同期処理はどっちに書く?

非同期処理はActionに書かなければないですが、同期処理はどちらに書くべきか?
ここで、Actionに渡されたtextが"Yes"ならcount+1、"No"ならcount-1、それ以外はそのままというStateについて考えてみます。

new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        plus (state, num) {
            state.count += num;
        },
    },
    actions: {
        vote (context, text) {
            if (text === 'Yes') {
                context.commit('plus', 1);
            } else if (text === 'No') {
                context.commit('plus', -1);
            }
        },
    },
}

このように、MutationはStateの変更にとどめておき、Actionで処理を行うというようにしたほうが各処理の責務が明確になっていい気がする。
(そもそも、文字列の条件分岐はComponentのほうでやったほうがいいんじゃないの、というのは置いといて)

でも、その変更処理がstateの状態に依存する変更ならMutationで処理を行いたい。
例えば、0~9までカウントアップして、9の次はまた0に戻るような処理を書く場合。

new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        countup (state, num) {
            state.count = (state.count + num) % 10;
        },
    },
    actions: {
        increment (context) {
            context.commit('countup', 1);
        },
    },
}

できるだけ、stateを直接参照するのもMutationの内側に閉じ込めてしまいたい。

Componentから直接commit

Vuexでは公式でComponentからMutationを直接commitすることを許可しています。

image.png
ただ、この図にはComponentから直接commitするルートがないんですよね。
もともとはたぶん図のほうで、Componentからの操作はActionに限定させたいという思想があったのだと思います。
ただ、それだと単純な状態の操作を作るときにコードが冗長になる(commitするだけのActionが乱立する)ので、これが許可されたのではないかと思います。
なので、できるだけAction経由で呼び出したほうがいいのではないかと思います。

mutation-types.js

Componentに対して公開するのをActionに限定するという考えを進めていくと、mutation-types.js(Mutationのタイプを定数化して外出しにするためのjs)は、action-types.jsにしたほうがよいのではないかと思えてきます。
もちろん、commitもdispatchも文字列で呼び出すことからMutationのタイプも定数で定義したほうがいいと思いますが、外に出すのはActionのほうではないかと。

結論

あくまで個人的な意見ですが

  • Mutationは状態の変更のみを行う(privateな(Actionだけから呼ばれる)セッター)
  • Actionは処理の公開や複雑な処理を行う(publicなメソッド)

というイメージです。
どうもJavaの考えに引きずられてる感じはありますね。

参考

Vuex 公式

241
167
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
241
167

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?