VuexのmapStateは書き方にバリエーションがある。ここではできるだけ多くのパターンを紹介する。
まず、話を具体的にするために次のようなストアを前提にする。
const profile = {
  namespaced: true,
  state: { twitter: "@suin", facebook: null, text: "よろしく〜" }
};
const user = {
  namespaced: true,
  state: { name: "suin" },
  modules: { profile }
};
const post = {
  namespaced: true,
  state: {
    title: "VuexのmapStateの書き方",
    tags: ["JavaScript", "Vue", "Vuex"]
  }
};
const store = new Store({
  state: { isLoggedIn: true },
  modules: { user, post }
});
従って、ストアのステートは次の図示のようになる。isLoggedInはルート直下のステートで、モジュールではない。userとprofile、postはモジュールだ。userとprofileはネストした構造にした。
なお、以下で示すサンプルコードの実行はCodePenのVuex: mapState patternsで行った。
mapStateを使う前のおまじない(定型文)
VueコンポーネントでmapStateを使うためには、vuexライブラリからmapStateをインポートする必要がある。コンポーネントの<script>タグのあたまに書いておこう。
<script>
import {mapState} from 'vuex'
...
mapStateの書き方パターン集
 普通のバインド
 普通のバインド
通常のバインドの書き方。
構文
computed: mapState(["ステートのキー"])
// 複数のステートをバインドすることもできる
computed: mapState(["ステートのキー", "ステートのキー", ...])
 次のような配列でない使い方はできず、
Uncaught TypeError: Cannot convert undefined or null to objectというエラーが発生する。
mapState("ステートのキー") // エラー
isLoggedInをバインドする例
const app = {
  name: "app",
  computed: mapState(["isLoggedIn"]),
  template: `<p>{{isLoggedIn}}</p>`
};
バインドされた状態
isLoggedIn: true
isLoggedInとuserをバインドする例
const app = {
  name: "app",
  computed: mapState(["isLoggedIn", "user"]),
  template: `<p>{{isLoggedIn}}{{user}}</p>`
};
バインドされた状態
isLoggedIn: true
user:
  name: "suin"
  profile:
    facebook: null
    text: "よろしく〜"
    twitter: "@suin"
 別名のバインド
 別名のバインド
ストアのステートを別名でバインドする書き方。
構文
computed: mapState({
  別名: "ステートのキー"
})
// 複数のステートをバインドすることもできる
computed: mapState({
  別名: "ステートのキー",
  別名: "ステートのキー",
  ...
})
isLoggedInをisSignedInと呼称しつつバインドする例
const app = {
  name: "app",
  computed: mapState({
    isSignedIn: "isLoggedIn"
  }),
  template: `<p>{{isSignedIn}}</p>`
};
バインドされた状態
isSignedIn: true
 モジュール内のステートのバインド
 モジュール内のステートのバインド
構文
computed: mapState("モジュールのパス", ["モジュール内のステートのキー"])
// モジュール内の複数のステートをバインドすることもできる
computed: mapState("モジュールのパス", ["モジュール内のステートのキー", "モジュール内のステートのキー", ...])
user.profileをバインドする例
const app = {
  name: "app",
  computed: mapState("user", ["profile"]),
  template: `<p>{{profile}}</p>`
};
バインドされた状態
profile:
  facebook:null
  text: "よろしく〜"
  twitter: "@suin"
user.profile.twitterをバインドする例
const app = {
  name: "app",
  computed: mapState("user/profile", ["twitter"]),
  template: `<p>{{twitter}}</p>`
};
バインドされた状態
twitter: "@suin"
user.profile.textとuser.profile.twitterをバインドする例
const app = {
  name: "app",
  computed: mapState("user/profile", ["text", "twitter"]),
  template: `<p>{{text}}{{twitter}}</p>`
};
バインドされた状態
text: "よろしく〜"
twitter: "@suin"
 算出プロパティとステートの共存
 算出プロパティとステートの共存
オブジェクトスプレッド演算子(...)を使う必要がある。
構文
computed: {
  ...mapState(["ルートステートのキー"]),
  算出プロパティ1() { /* ... */ },
  算出プロパティ2() { /* ... */ },
  ...
}
算出プロパティがあるコンポーネントにisLoggedInをバインドする例
const app = {
  name: "app",
  computed: {
    ...mapState(["isLoggedIn"]),
    date() {
      return new Date()
    }
  },
  template: `<p>{{isLoggedIn}} {{date}}</p>`
};
算出プロパティ
date: "2018-01-07T11:11:03.779Z"
バインドされた状態
isLoggedIn: true
 複数モジュールのモジュール内ステートのバインド
 複数モジュールのモジュール内ステートのバインド
オブジェクトスプレッド演算子(...)を使う必要がある。
構文
computed: {
  ...mapState("モジュール名", ["モジュールステートのキー"]),
  ...mapState("モジュール名", ["モジュールステートのキー"]),
  ...
}
user.nameとpost.title、post.tagsをバインドする例
const app = {
  name: "app",
  computed: {
    ...mapState("user", ["name"]),
    ...mapState("post", ["title", "tags"])
  },
  template: `<p>{{name}} {{title}} {{tags}}</p>`
};
バインドされた状態
name: "suin"
tags: 
  0: "JavaScript"
  1: "Vue"
  2: "Vuex"
title: "VuexのmapStateの書き方"
 モジュール内ステートの別名バインド
 モジュール内ステートの別名バインド
構文
computed: mapState("モジュールのパス", {
  別名: "モジュール内のステートのキー"
})
user.nameをuserNameと呼称しながらバインドする例
const app = {
  name: "app",
  computed: mapState("user", {
    userName: "name"
  }),
  template: `<p>{{userName}}</p>`
};
バインドされた状態
userName: "suin"
 ステート加工結果のバインド
 ステート加工結果のバインド
ステートをそのままバインドするのではなく、ステートを加工した結果をバインドする方法。
構文
computed: mapState({
  加工後の名称: state => 加工処理(state.加工対象のステート名)
})
isLoggedInを加工した結果をisLoggedOutとしてバインドする例
const app = {
  name: "app",
  computed: mapState({
    isLoggedOut: state => !state.isLoggedIn
  }),
  template: `<p>{{isLoggedOut}}</p>`
};
バインドされた状態
isLoggedOut: false
 複雑なバインド
 複雑なバインド
モジュールをまたいだ複雑なバインドをする方法。
isLoggedIn、user.name、post.titleをバインドする例
const app = {
  name: "app",
  computed: mapState({
    isLoggedIn: "isLoggedIn",
    userName: state => state.user.name,
    postTitle: state => state.post.title
  }),
  template: `<p>{{isLoggedIn}} {{userName}} {{postTitle}}</p>`
};
バインドされた状態
isLoggedIn: true
postTitle: "VuexのmapStateの書き方"
userName: "suin"
質疑応答
質問などは、ここにコメントを残すかsuinのプログラミング相談室(チャット)で話しかけてください。どんな些細なものでも構いません。
