質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

vuex mapActionsの使い方 引数としてpayload値を渡したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,949

holic

score 119

 vuexメソッド mapActionsを使いたいです。そして引数をセットしたいです。

vuexメソッド mapActionsを実装したいのですが、調べて実践してみましたが、エラーが出てしまい正しく実装できませんでした。
mapActionsを使うに、前正常に動くソースを記します。

index.vue

<template>
  <section class="container posts-page">
      <div slot="header" class="clearfix">
        <time>{{ msg }}</time>

        <v-text-field
          label="ユーザーID"
          v-model="payload.id"
        ></v-text-field>
        </div>

        <v-btn color="success" @click="register()">新規ID作成</v-btn>
        <transition name="fade" mode="out-in">
          <div v-if="users">
          <h2>usersId一覧</h2>
            <p>{{ users }}】さん</p>
          </div>
        </transition>

  </section>
</template>

<script>
import { mapGetters,mapActions } from "vuex";

export default {
  asyncData() {
    return {
      msg: "新しくユーザを追加することができます",
      payload: { id: null }
    };
  },
  methods: {
    async register() {
      await this.$store.dispatch("users/register", { ...this.payload });
      this.payload.id = null;
      //this.$router.push("/posts/");
    }
  },
  computed: {
    ...mapGetters("users", ["users"])
  }
};
</script>

vuexの記述

store/users.js

export const state = () => ({
    isLoggedIn: false,
    users: null
})

export const getters = {
    isLoggedIn: state => state.isLoggedIn,
    users: state => state.users

}

export const mutations = {
    setUsers(state, users) {
        //console.log(users)
        state.isLoggedIn = true
        state.users = users
    },
}

export const actions = {
    async register({ commit }, payload) {
        //console.log(users)
        const users = payload.id
        commit('setUsers', users)
    }
}


この2ファイルで目的としている動きは実装出来ておりました。
これからはより効率的で可読性があるものにしたく、mapActionsを使ってみます。

mapActionsに書き換えたソース

index.vueファイルのscript文だけ抜粋します。

<script>
import { mapGetters,mapActions } from "vuex";

export default {
  asyncData() {
    return {
      msg: "新しくユーザを追加することができます",
      payload: { id: null }
    };
  },
  methods: {
      ...mapActions('users',['register'])
      this.register(this.payload)
      this.payload.id = null
  },
  computed: {
    ...mapGetters("users", ["users"])
  }
};
</script>

エラー

イメージ説明

vuexのissueで解決策と思われる記事を発見、試してみましたが・・・

vuexのissueで同じような悩みを持った人がいましたのでこれのとおり実装しました。
しかしerrorでした。
vuexのissue

 実現したいことまとめ

  • mapActionsを使いたい。
  • 対応するActionsのメソッドregisterに引数としてpayload値を持たせて、dispatchしてほしい。
  • dispatchが完了後に、payload値をnullにしたいです。この場合はasync awaitを使って実装するべきなのでしょうか。非同期についてあまり詳しくなく、もしawaitさせるべきでしたらさせたいです。

vue,vuexに詳しい方がいらっしゃいましたらお手数ではご教示をお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

解決自体は簡単ですが、今後のためにエラーの解説をしておきます。

今回のエラーSytaxError: G:\nuxttest2\pages\users\index.vue: Unexpected token, expected "," (36:6)は、以下の通り解釈します。

  1. SyntaxErrorはエラーの種別です。どんなエラーが起きているかを判断します。
  2. G:\nuxttest\...はエラーが検知されたファイルパスです。
  3. Unexpected tokenは、ある文字がJavaScriptの文法上期待されない箇所で検知されたということです。
  4. expected ","は、期待されていた文字です。
  5. (36:6)はエラーが検知されたファイル中の箇所で(何番目の行か:何番目の文字か)を表します。ただし、これはエラーが検知された場所で、実際に修正すべき原因は、それ以前にあるかもしれません。

今回の場合では、index.vueの36行目6文字目でエラーが検知されています。

  methods: {
      ...mapActions('users',['register'])
      this.register(this.payload)
      this.payload.id = null
  },

methodsにオブジェクトを設定しようとしていますが、
オブジェクトの基本形は以下の通りで、キー→値→(カンマ)の繰り返しが期待されます。

{ key1: value1, key2: value2 }

スプレッド構文はオブジェクトを別のオブジェクトに展開するものです。

var obj1 = { a: 1, b: 2 };
var obj2 = { ...obj1, c: 3 } // { a: 1, b: 2, c: 3 }

今回のケースでは、
オブジェクトの中で...mapActions('users',['register'])のあとにthis.register(this.payload)が記述されていることが問題です(文字通りexpected ","です)。

mapActionsは、アクションするだけのメソッドを、アクションと同名のメソッドとして展開してくれる(アクションするだけのメソッドを自分で繰り返し書かなくて良い)ものです。
this.register(this.payload)this.payload.id = nullなどは、別のメソッドとしてまとめて、mountedなど、Vueコンポーネントのライフサイクル適切なタイミングで呼び出しましょう。

 補足

プログラミング中にエラーが起きた時は、表示されたエラー内容を読解する習慣をつけると、今後自力で解決する力になります。
こちらなどを参考に、まずは「どんなエラーがでているのか」だけでも確認されるといいと思います。
または、ライブラリなどのエラーであれば、エラーメッセージで検索するとヒットすると思います。

 追記(2018/11/13)

テストしてませんが、最終的なコードはおおむね以下のようになると思います。

メソッド名のregisterAndClearPayloadは内容から判断して適当に命名しています。
いずれにせよ、今回問題だったのは、オブジェクトの書き方が違っていたことです。

<script>
import { mapGetters,mapActions } from "vuex";

export default {
  asyncData() {
    return {
      msg: "新しくユーザを追加することができます",
      payload: { id: null }
    };
  },
  methods: {
    ...mapActions('users',['register']),
    registerAndClearPayload: function() {
      // mapActionsにより、this.register()メソッドとして、
      // this.$store.dispatch('users/register', /* 引数 */) を実行するメソッドが登録されている
      this.register(...this.payload)
      this.payload.id = null
    },
  },
  computed: {
    ...mapGetters("users", ["users"])
  }
};
</script>

ただ、身も蓋も無いのですが、今回の場合コンポーネントのデータpayloadはVuexに管理させた方がいいかもしれません。見たところ「ユーザーID」であり、Vuexで管理しているものと同じ値なので。
「あるデータは、1箇所で管理すべき」(Single source of truth)(意訳)というプログラミングにおける原則があります。
そうしたら、this.payload.id = nullをどう呼び出せばいいかも考えなくて良いのでは?

 追記(2018/11/13)

ただ、身も蓋も無いのですが、今回の場合コンポーネントのデータpayloadはVuexに管理させた方がいいかもしれません。見たところ「ユーザーID」であり、Vuexで管理しているものと同じ値なので。
「あるデータは、1箇所で管理すべき」(Single source of truth)(意訳)というプログラミングにおける原則があります。
そうしたら、this.payload.id = nullをどう呼び出せばいいかも考えなくて良いのでは?

最終的な実装がわからない上での発言であり、蛇足です。
スルーしてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/13 14:07 編集

    NozomuIkuta様
    丁寧に解説文をいただきまして、ありがとうございます。
    まだまだプログラマーとして至らない点が多いために勉強になります、エラー文章の解読にも今後注目をして進めたいと思います。

    そして、私の理解力不足なのか、回答いただいた内容についてわからないところがあったので、申し訳ありませんが、さらに質問をさせてください。。。

    ・methodsには`...mapActions("users", ["register"])`だけを記述するという意味でしょうか。
    そして、それとは別にregisterに対しての引数をセットするということなのでしょうか。

    ・>this.register(this.payload)やthis.payload.id = nullなどは、別のメソッドとしてまとめて、mountedなどライフサイクルの適切なタイミング

    ボタン要素を押下したときにregisterを発動させたいので、methodsに記述が適切かと思いました。mountedはページが読み込まれたときの一回しか発動しないと理解しておりましたが・・・・。

    理解が悪くて本当に申し訳ありません。上記を踏まえて、追記でソースを記述しました。
    レンダリングには成功しましたが、ボタン(register発火)を押したときにはエラー文がコンソールに出力されました。

    Unhandled promise rejection TypeError: "payload is undefined"

    エラー文から察するにstore/users.jsのregisterに引数がセットされておりません。という意味かと思いました。

    キャンセル

  • 2018/11/13 14:43

    追記しました。
    「ライフサイクル」の件は、こちらが間違っていました。ご指摘ありがとうございます。
    該当箇所に取り消し線をいれておきました。

    キャンセル

  • 2018/11/13 15:04

    解答ソースありがとうございます。理解できました。
    私の質問はこれで解決です。

    >今回の場合コンポーネントのデータpayloadはVuexに管理させた方がいいかもしれません。
    すこしずつvue勉強していってますので今回も大変参考になる考察をいただけたことは大きいです。
    payloadをvuexに入れるとは考えになかったでした。ありがとうございます。

    キャンセル

  • 2018/11/13 15:11

    解決したようでよかったです。

    Vuexができた理由のひとつが「いろんなコンポーネントで別々に、共通した状態(データ)を管理するのきついよね」ということです。

    ただ、各コンポーネントに持たせた方がいいデータもあります。
    それは、データとコンポーネントの寿命が一致する場合です。
    (例:一時的に出現し消滅するコンポーネントに固有のデータなど)
    こちらは、全体共通で管理する意味がない(うすい)からです。

    適材適所で使い分けてみてください。

    キャンセル

+1

issueで言っているのはおそらくこういうことですね。

methods: {
    ...mapActions('users',['register']),
    hoge() {
        this.register(this.payload)
        this.payload.id = null
    }
},

これは

methods: {
    register(payload) {
        this.$store.dispatch('users/register', payload)
    },
    hoge() {
        this.register(this.payload)
        this.payload.id = null
    }
},

と同等と考えるとわかりやすいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/13 15:06

    de9様
    ご返答いただきました、ありがとうございました。
    理解が深まりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る