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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

1140閲覧

Nuxt.ts+vuex-class-componentでError: [vuex] do not mutate vuex store state outside mutation handlers.

reud

総合スコア21

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2019/08/09 16:30

編集2019/08/09 16:36

該当ソースコード

このブランチこのコミット

問題: v-btnの@clickに以下のメソッドを結び付けて発火すると

typescript

1 public setMock() { 2 // オブジェクトのコピー(代入だと参照渡しになるため。) 3 this.mockNumber++; 4 const m = deviceDataMock; 5 m.ipAddress = `192.168.0.${this.mockNumber}`; 6 vxm.devices.SET_DEVICE_DATA(m); 7}

下記のエラーが発生する。
Error: [vuex] do not mutate vuex store state outside mutation handlers.

store/index.tsは以下の定義になっている

typescript

1import { 2 action, 3 getter, 4 Module, 5 mutation, 6 VuexModule 7} from 'vuex-class-component'; 8import Vuex from 'vuex'; 9import Vue from 'vue'; 10import { DeviceData, DeviceDataState } from '../types'; 11import { deepCopy } from '@/utilities'; 12 13Vue.use(Vuex); 14// いつか消したい 15export const strict = false; 16 17// for TS1219 18@Module({ namespacedPath: 'devices/', target: 'nuxt' }) 19// @ts-ignore 20export class DeviceDataStore extends VuexModule implements DeviceDataState { 21 // @ts-ignore 22 @getter deviceData: DeviceData[] = []; 23 @getter deviceMap = new Map(); 24 25 @mutation 26 public SET_DEVICE_DATA(payload: DeviceData) { 27 this.deviceData.push(deepCopy(payload)); 28 this.deviceMap.set(deepCopy(payload).ipAddress, deepCopy(payload)); 29 } 30 31 @mutation 32 public CHANGE_DEVICE_DATA(payload: DeviceData[]) { 33 this.deviceData = payload; 34 this.deviceMap.clear(); 35 this.deviceData.forEach((v) => this.deviceMap.set(v.ipAddress, v)); 36 } 37 38 @action({}) 39 // @ts-ignore 40 public initialize() { 41 // actions内で簡単にthisからmutationを呼び出せる。 42 this.CHANGE_DEVICE_DATA([]); 43 this.deviceMap.clear(); 44 } 45} 46 47const store = new Vuex.Store({ 48 modules: { 49 devices: DeviceDataStore.ExtractVuexModule(DeviceDataStore) 50 } 51}); 52 53export default DeviceDataStore.ExtractVuexModule(DeviceDataStore); 54 55export const vxm = { 56 devices: DeviceDataStore.CreateProxy(store, DeviceDataStore) 57}; 58

また、types/index.tsは以下のようになっている

export interface Item { icon: string; title: string; to: string; } export interface DeviceData { ezRequesterModels: EzRequesterModel[]; deviceType: DeviceTypes; ipAddress: string; hostname: string; description: string; } export interface DeviceDataState { deviceData: DeviceData[]; } export interface EzRequesterModel { protocol: RequestTypes; protocolModel: string; parameterModel: string; } export enum DeviceTypes { RaspberryPi3BPlus = 'Raspberry Pi 3B+', RaspberryPiZero = 'Raspberry Pi zero W (WH)', Etc = 'Etc' } export enum RequestTypes { HTTP = 'http', HTTPS = 'https' }

mocks/index.tsは下記の通り

import { DeviceData, DeviceTypes, RequestTypes } from '../types'; export const deviceDataMock: DeviceData = { ezRequesterModels: [ { protocol: RequestTypes.HTTP, protocolModel: 'http', parameterModel: 'hogehoge?exam=hoge' }, { protocol: RequestTypes.HTTPS, protocolModel: 'https', parameterModel: 'hogehoges?exams=hoges' } ], deviceType: DeviceTypes.Etc, ipAddress: '192.168.0.xxx', hostname: 'example.local', description: 'The Woodman set to work at once, and so sharp was his axe that the tree was soon chopped nearly through.' };

また、deepcopyされていないのが原因だと思い、以下の関数を使用しているが変化はなかった

export const deepCopy = <T>(target: T): T => { if (target === null) { return target; } if (target instanceof Date) { return new Date(target.getTime()) as any; } if (Array.isArray(target)) { const cp = [] as any[]; (target as any[]).forEach((v) => { cp.push(v); }); return cp.map((n: any) => deepCopy<any>(n)) as any; } if (typeof target === 'object' && target !== {}) { const cp = { ...(target as { [key: string]: any }) } as { [key: string]: any; }; Object.keys(cp).forEach((k) => { cp[k] = deepCopy<any>(cp[k]); }); return cp as T; } return target; };

試したこと(全てダメだった)

  • スプレッド演算子を使用してみる
  • deepcopy()を使ってみる(上記のもの)
  • 新たに定義してみる
{ ezRequesterModels: [ { protocol: RequestTypes.HTTP, protocolModel: 'http', parameterModel: 'hogehoge?exam=hoge' }, { protocol: RequestTypes.HTTPS, protocolModel: 'https', parameterModel: 'hogehoges?exams=hoges' } ], deviceType: DeviceTypes.Etc, ipAddress: '192.168.0.xxx', hostname: 'example.local', description: 'The Woodman set to work at once, and so sharp was his axe that the tree was soon chopped nearly through.' };

☝️これをそのまま代入してみてもエラーになってしまう。

気になること

  • Home画面には反映されているので保存はされているみたいである。

しばらく調べていたのですがどうやっても手掛かりがつかめず、ここに質問させて頂きました。

どなたか提案や解決法をご存知の方いらしたら教えていただきたいです。

該当エラー

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

解決しました。

store/index.tsを以下のように変更しました。

typescript

1import { 2 action, 3 getter, 4 Module, 5 mutation, 6 VuexModule 7} from 'vuex-class-component'; 8import Vuex from 'vuex'; 9import Vue from 'vue'; 10import { DeviceData, DeviceDataState } from '../types'; 11import { deepCopy } from '@/utilities'; 12 13Vue.use(Vuex); 14// いつか消したい 15export const strict = false; 16 17// for TS1219 18@Module({ namespacedPath: 'devices/', target: 'nuxt' }) 19// @ts-ignore 20export class DeviceDataStore extends VuexModule implements DeviceDataState { 21 // @ts-ignore 22 @getter deviceData: DeviceData[] = []; 23 @getter deviceMap = new Map(); 24 @mutation 25 public SET_DEVICE_DATA(payload: DeviceData) { 26 this.deviceData.push(deepCopy(payload)); 27 this.deviceMap.set(deepCopy(payload).ipAddress, deepCopy(payload)); 28 } 29 30 @mutation 31 public CHANGE_DEVICE_DATA(payload: DeviceData[]) { 32 this.deviceData = payload; 33 this.deviceMap.clear(); 34 this.deviceData.forEach((v) => this.deviceMap.set(v.ipAddress, v)); 35 } 36 37 @action({}) 38 // @ts-ignore 39 public initialize() { 40 // actions内で簡単にthisからmutationを呼び出せる。 41 this.CHANGE_DEVICE_DATA([]); 42 this.deviceMap.clear(); 43 } 44} 45 46export const devices = DeviceDataStore.ExtractVuexModule(DeviceDataStore); 47 48const store = new Vuex.Store({ 49 modules: { 50 devices 51 } 52}); 53 54export const vxm = { 55 devices: DeviceDataStore.CreateProxy( 56 store, 57 DeviceDataStore 58 ) as DeviceDataStore 59}; 60

投稿2019/08/10 01:24

reud

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問