vuex-class-componentをアップデートしたらAPIが変わっていました

こんにちは。サービスグループの武田です。

Vue+TypeScriptで開発する際に、Vuexをタイプセーフに扱うためのライブラリとしてvuex-class-componentを以前紹介しました。

vuex-class-componentを使ってVuexをクラススタイルでタイプセーフに書いてみよう

先日ライブラリをアップデートしたら、動かなくなりました。どうやら書き方が変わっていたらしいので、変更点などを紹介します。なおvuex-class-componentのバージョンを最新にした際の変更点を紹介しているため、途中のバージョンで変更されたものもまとめて変更点として挙げています。

なお、ソースコードは前回のリポジトリを更新する形でGitHubに置いてあります(blog2タグを振ってあります)。

TAKEDA-Takashi/example-vuex-counter-app-class-style at blog2

検証環境

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.6
BuildVersion:	18G2022

$ npm list vue vuex vuex-class-component
example-vuex-counter-app-class-style@0.1.0 /path/to/example-vuex-counter-app-class-style
├── vue@2.6.11
├── vuex@3.1.2
└── vuex-class-component@2.2.1

ライブラリを最新化

もともと使っていたライブラリのバージョンの多くが古くなっていたため、まずは最新化を行いました。素直に更新しているだけなので説明は省きます。

$ npm install -D @vue/cli npm-check-updates
$ npx ncu -u && npm install
$ npm audit fix

ソースコードを修正

アップデートしたこの段階で実行してみるとエラーが出ます。ここでうまくいっていればこのエントリは書いていないはずですね。

@actionアノテーションでエラーが発生していますが、実際には全体的に書き換える必要がありました。具体的に挙げると次の修正が必要です。

  • クラスに付与する@Moduleが不要になり、代わりにVuexModuleを作成してそれを継承する
  • stateに付与する@getterが不要になった
  • actionに付与する@actionの引数がオプションになり、メソッドのasyncが必須になった
  • Vuexモジュールの抽出はextractVuexModule関数を使用する
  • Storeプロキシの作成はcreateProxy関数を使用する

mutationとgetterの定義方法は変わっていませんでした。

diff --git a/src/store.ts b/src/store.ts
index fed940d..ef1ed42 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -1,13 +1,14 @@
+import { action, createModule, createProxy, extractVuexModule, mutation } from 'vuex-class-component';
+
 import Vue from 'vue';
 import Vuex from 'vuex';
-import { VuexModule, mutation, action, getter, Module } from 'vuex-class-component';

 Vue.use(Vuex);

-@Module({ namespacedPath: 'counter/' })
+const VuexModule = createModule();
+
 export class CounterStore extends VuexModule {

-  @getter
   public count: number = 0;

   @mutation
@@ -20,14 +21,14 @@ export class CounterStore extends VuexModule {
     this.count--;
   }

-  @action()
-  public incrementIfOdd() {
+  @action
+  public async incrementIfOdd() {
     if ((this.count + 1) % 2 === 0) {
       this.increment();
     }
   }

-  @action()
+  @action
   public async incrementAsync() {
     return setTimeout(() => this.increment(), 1000);
   }
@@ -35,12 +36,12 @@ export class CounterStore extends VuexModule {

 const store = new Vuex.Store({
   modules: {
-    counter: CounterStore.ExtractVuexModule(CounterStore),
+    ...extractVuexModule(CounterStore),
   },
 });

 export default store;

 export const vxm = {
-  counter: CounterStore.CreateProxy(store, CounterStore),
+  counter: createProxy(store, CounterStore),
 };

以上の修正をすると無事に動作するようになりました。

まとめ

Vue 3のリリースに期待感が膨らみますね。リリースされるとVuexなどの周辺ライブラリも使い方が変わってくるはずです。そもそもVuexは不要になる可能性もあります。どうなっていくのか楽しみですね。