vuexfireとfirestoreがうまく連携しない？個人的躓きポイント

firestoreとvuexをサクッと同期させるのに便利なvuexfire。

こちらのページでは[NUXTとFirebaseでファイヤーエンブレム風ゲーム作ってみた](https://qiita.com/obekohei/items/4c79604cdb2e4eae14bf) にて使用したvuexfireで躓いたポイントをまとめています。


なお、vuexfireの詳細や使い方については下記公式ページをご確認ください。

[vuexfire 公式](https://vuefire.vuejs.org/vuexfire/)
[vuexfire github](https://github.com/posva/vuexfire)

ちなみに私のvuexfireのバージョンは3.2.2、フレームワークはnuxtの2.0.0を使用しています。

## 躓きポイント1 firestoreを更新したのにvuexfireが更新されない！

まず、vuexfireの大前提として、データを同期させるにはfirestoreを更新しなければならない、ということです。

vuexを更新してもfirestoreにデータは反映されません。常にfirestore→vuexという順番でデータが更新される必要があります。

[Binding / Subscribing to changes](https://vuefire.vuejs.org/vuexfire/binding-subscriptions.html#binding-in-actions)

> However,  this synchronisation is only one-way. Do not modify the local variable (e.g. doing this.user.name = 'John'), because (a) it will not change the remote Database and (b) it can be overwritten at any time by Vuexfire.

要するにvuexの値を更新してもfirestoreの値は更新されないし、むしろ後で更新したfirestoreの値でvuexの値が上書きされてしまうから気をつけてねってことですね。

ただ、私がはまったケースとして、 **一度vuexfireを更新してしまうと、そのあとfirestoreを更新してもデータが同期しなくなる** 、という現象にでくわしました。

発生する手順ですが、

1. bindFirestoreRefでfirestoreとvuexのデータを同期させる
2. そのあと、vuexのデータだけ更新する
3. vuexと同期させていたfirestoreのデータを更新してもvuexの値が上書きされない

のような感じです。

firestoreと同期させていたvuexの値を更新すると、参照が外れるかのごとく、その後firestoreの値を更新してもvuexの値が更新されなくなってしまいます。

公式サイトを一通り確認しましたが、firestoreと同期させたvuexの値を更新するとfirestoreの参照が外れてしまう、というようなことについては書かれていませんでした。(見落としている場合、そう指摘してもらえると嬉しいです)

まあ、確かに「ローカル(vuex)の値は変更するな！」と公式にも書かれていて、やるなといってることをやってるんだから挙動が変になってしまうのも無理ないんだろうが。

そもそもなぜこのようなことをしたのかというと、クライアントで値を更新する度にfirestoreとやりとりしてしまうとfirestoreの書き込み回数が無駄に増えてしまうからです。

なので、ある一定の期間はローカルだけで修正を保持しておき、その後、特定のタイミングでローカルの修正をfirestoreに一気に反映させれば書き込み回数は減らせます。

そうすると上記のような現象と出会い、「なんで更新されないんだー！」みたいにはまってしまいました。

解決策としては、外れたときはbindFirestoreRefでもう一度繋げばOKです。

## 躓きポイント2 unbindするときに、resetをfalseにできない！

vuexfireではbindFirestoreRefで同期させたデータを、unbindFirestoreRefでいつでもその同期を外すことができます。

そして同期の外し方にも２パターンあって、同期を外した時に元の値をリセット(null)するか、元の値を残しておくか、unbindFirestoreRefの第二引数を指定することが選択できるようになっています。

```
// store.js
export default new Vuex.Store({
  // other store options are omitted for simplicity reasons

  actions: {
    someAction: firestoreAction(({ state, bindFirestoreRef, unbindFirestoreRef }) => {
      unbindFirestoreRef('todos')
      // or
      unbindFirestoreRef('todos', true)
      // state.todos === []

      // using the boolean version
      unbindFirestoreRef('todos', false)
      // state.todos === [{ text: 'Use Firestore Refs' }]

      // using the function syntax
      unbindFirestoreRef('todos', () => [{ text: 'placeholder' }])
      // state.todos === [{ text: 'placeholder' }]

      // documents are reset to null instead, you can also provide the same options as above
      unbindFirestoreRef('doc')
      // state.doc === null
    }),
  },
})
```
[https://vuefire.vuejs.org/vuexfire/binding-subscriptions.html#unbinding](https://vuefire.vuejs.org/vuexfire/binding-subscriptions.html#unbinding)より引用

ですが私の場合、なぜかこのunbindFirestoreRefの第二引数に値を指定しようとすると**引数が一つしか指定できない**、とエラーがでます。

```battleRoom.ts
  unBindBattleRoomRef: firestoreAction(({ unbindFirestoreRef }) => {
    return unbindFirestoreRef('battleRoom', false←ここでエラーがでる)
  }),
```

「公式では指定できるって書いてるのになんで！？」ってvuexのバージョンが最新じゃないのか、何か違う関数使っているのか、など公式ページやvuexのgithubのページなんかを隅々まで確認してみたものの、どうしても解決策がわからず。

もう半ば諦めて「もうエラー出てるけどダメ元でコード走らせてみるか...」と、エラー無視して挙動を確認してみると、 **ちゃんと動いてるやないかい...!** 

どうやら、vuexfireの型定義ファイルに誤りがあるのか、第二引数は普通に指定できました。これだけで何時間か無駄に時間を浪費してしまった...

```battleRoom.ts
  unBindBattleRoomRef: firestoreAction(({ unbindFirestoreRef }) => {
    // @ts-ignore ← これ入れたらとりあえずエラーはやり過ごせる
    return unbindFirestoreRef('battleRoom', false)
  }),
```

## vuexfire使ってみた感想は？

と、振り返ってみてvuexfireでつまずいたポイントは２つしか見つかりませんでしたが、感覚的にはもっとvuexfireに手こずった印象があります。

特にどこまで参照を保持していて、どこからは参照を解放して、みたいな管理が面倒くさかったです。まあ、でもこれはvuexfireというよりfirestoreを使う上では仕方がないのかもしれないけど。

ただ、慣れてしまえば便利なのは間違いないので、firestore + Vue(or Nuxt)とかでアプリ作る人はぜひ試してもらえればと思います。

ちなみに冒頭でもお話ししましたが、こちらのページは[NUXTとFirebaseでファイヤーエンブレム風ゲーム作ってみた](https://qiita.com/obekohei/items/4c79604cdb2e4eae14bf)で使ったvuexの躓きポイントになりますので、興味のある方はそちらの記事もよろしければみていってもらえれば嬉しいです。

終わり。