Vuex4 rc 2 がリリースされるけど、何が変わるのか詳しくわかっていなかったので調べてみた

## タイトルの通りです
具体的に何が変わったのか詳しく知りたいと思い、調べてみました。

## リリース情報を見てみました
https://github.com/vuejs/vuex/releases/tag/v4.0.0-rc.2

### Bug Fixes
- fix getters stop working when component is destroyed
- stop throwing an error on hasModule when parent does not exists

### Features
- build: enable named esm module import on node.js >= 14

・・・自分の知識量だと「そうなんだぁ」くらいの感想しか出てこないので、説明や背景を読んで理解を深めることにしました。

## 2 つの Bug Fixes について興味を持ったので少し踏み込んで調べてみました
### 1 fix getters stop working when component is destroyed
https://github.com/vuejs/vuex/pull/1883 に詳細が書かれていたので読んでみました。
コンポーネントが破棄されると、getter がVueを介して破壊されるとのこと。
パターンとしては、コンポーネント内で `registerModule` でモジュールを登録し、ルートの切り替えのタイミングなどでコンポーネントが破棄すると、更新したデータが消えてしまう。

実際に問題が起きるのかを確認するために、https://github.com/vuejs/vuex/issues/1878 で紹介しているリポジトリ・操作手順で確認してみました。
※ちなみに、最新のリポジトリの vuex のバージョンが `4.0.0-0` になっているため、動作確認してみたい場合はバージョン変えてみて試してみてください。

#### バージョン
Vuex 4.0.0-rc.1

#### コード
```Home.vue
<template>
  <div class="home">home page</div>
  <h2>state.common.count {{ commonCountGetter }}</h2>
  <h2>state.home.count {{ countHomeGetter }}</h2>
  <button @click="produceError">
    Produce error
  </button>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { mapGetters, mapMutations, mapActions } from "vuex";
import homeStore from "../store/homeStore";

@Options({
  computed: {
    ...mapGetters("common", ["commonCountGetter"]),
    ...mapGetters("home", ["countHomeGetter"]),
  },
})
export default class Home extends Vue {
  produceError() {
    return this.$store.hasModule(['second', 'third'])
  }
  beforeCreate() {
    if (!this.$store.state.home) {
      this.$store.registerModule("home", homeStore);
    }
  }
}
</script>
```
・・・[Vue3 の RFC としてはリジェクトされた](https://github.com/vuejs/rfcs/pull/17)けど、[vue-class-component の Vue3 サポートは行われる](https://github.com/vuejs/vue-class-component/issues/402)とのことなので一旦次進みます。

#### ファイル構成
```
src
├── App.vue
├── router
│   └── index.ts
├── store
│   └── aboutStore
    │   ├── actions.ts
    │   ├── getters.ts
    │   ├── index.ts
    │   └── mutations.ts
│   └── commonStore
    │   ├── actions.ts
    │   ├── getters.ts
    │   ├── index.ts
    │   └── mutations.ts
│   └── homeStore
    │   ├── actions.ts
    │   ├── getters.ts
    │   ├── index.ts
    │   └── mutations.ts
│   └── index.ts
├── views
    │   ├── About.vue
    │   └── Home.vue
```

#### 操作手順
1. Home 画面を初期表示
2. About 画面へ遷移
3. Home 画面へ遷移

![データが消える.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201405/5ef77ff9-3cec-9c47-dd72-684aa52ea550.gif)

うん、ゾッとしました。
あと、個人的にそもそもコンポーネントごとにモジュールを登録して state のデータを参照・更新したことがなかったので、こんな使い方あるんだなっていう感想になっちゃいました。
複雑な Object とか、同じアイテムを Array で管理しないといけなくなった時みたいな、管理しづらい時に使うのが良いっていう認識で合ってるかな・・・。(もはやエラーに対しての感想じゃなくなってきてるという。)

### 2 stop throwing an error on hasModule when parent does not exists
https://github.com/vuejs/vuex/issues/1850 を確認しました。
ストアに登録されていないモジュールを、配列を使用して呼び出すと、false ではなく `TypeError: Cannot read property 'hasChild' of undefined` エラーがスローされちゃう、とのこと。

https://jsfiddle.net/xkLh4njp/ でボタンクリックしてみると、`TypeError: Cannot read property 'hasChild' of undefined` エラーがスローされることが確認できる。

この修正にあたって、「現時点では予想通りの動作なんだよね」ってところから始まって、エラーを修正するにあたっての懸念の抽出をし、「ドキュメントを明確にして、hasChild との役割を明確にすれば、このエラーは不要だよね」と結論を出して close していたので、自分もちゃんと現状の問題点・解決策を提示できるようにしないとなと感じました。(感想薄いな)


## まとめ
- [Reactivity's effectScope API](https://github.com/vuejs/rfcs/pull/212) の内容とやりとりを追おうと思いました。
- 画面を動かしながら理解するのは自分に合ってるなって改めて実感しました。
- 英語の勉強しよ。

そして，明日の 17 日目の投稿は， @mimaun さんです。お楽しみに！