LoginSignup
1
0

More than 3 years have passed since last update.

nuxtでfirestoreとvuexのstoreを組み合わせるとうまく保存できないのでラッパーにした話

Posted at

こんにちは。virapture株式会社もぐめっとです。
mogmet.jpeg
こんな格好してるので前世はきっと狛犬でした。しらんけど。

今回はnuxtとvuexのstoreとfirestoreの組み合わせのちょっとしたtipsを紹介します。

どんなときにエラーになるか

vuexのstoreってプリミティブな型(stringとかintとかDateとか基礎的なやつ)で保存しないと、こんなエラーはいちゃうんですよね。

vue.runtime.esm.js?2b0e:2107 Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at Function.[Symbol.hasInstance] (<anonymous>)
    at _traverse (vue.runtime.esm.js?2b0e:2107)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)
    at _traverse (vue.runtime.esm.js?2b0e:2123)


Uncaught Error: FIRESTORE (8.3.0) INTERNAL ASSERTION FAILED: Unexpected state
    at x (prebuilt-e065c69d-7a321be7.js?a931:160)
    at t.Sf (prebuilt-e065c69d-7a321be7.js?a931:15880)
    at t.enqueue (prebuilt-e065c69d-7a321be7.js?a931:15795)
    at t.Ps (prebuilt-e065c69d-7a321be7.js?a931:15783)
    at t.As (prebuilt-e065c69d-7a321be7.js?a931:5138)
    at eval (prebuilt-e065c69d-7a321be7.js?a931:5117)

何言ってるかわかんないからとても不親切なエラーです。

例えばよくあるのがfirestoreにあるドキュメントで、ある一つのプロパティがDocumentReferenceでデータが渡ってきて、それを持った状態でstoreに保存しちゃうとこんなエラーになっちゃいます。

対策

私はTypescriptで組んでいるのですがこんな感じで対策しました。

まずはinterfaceを準備します。

@types/firestore.d.ts
declare type DocumentReference = import('firebase/app').default.firestore.DocumentReference
declare interface IReferenceWrapper {
  readonly reference: DocumentReference
}
declare type FirestoreDocumentReference = DocumentReference | IReferenceWrapper

今回はVillageというエンティティを用意し、ユーザの情報を格納しているとします。

@types/village.d.ts
declare interface IVillage {
  readonly username: string
  readonly userReference: FirestoreDocumentReference
}

そして、今回の肝となるDocumentReferenceをプリミティブで持つラッパーを準備します。

entity/referenceWrapper.ts
import { firestore } from '~/plugins/firebase' // firestoreは各自いい感じに定義しておいてください

export default class ReferenceWrapper implements IReferenceWrapper {
  private readonly path: string
  get reference(): DocumentReference {
    return firestore.doc(this.path)
  }

  constructor(reference: FirestoreDocumentReference) {
    this.path = (reference as DocumentReference).path
  }
}

DocumentReferenceを使ってエンティティとなるクラスを作ります。

entity/village.ts
import ReferenceWrapper from '~/entity/referenceWrapper'
export class Village implements IVillage {
  readonly username: string
  readonly userReference: ReferenceWrapper

  constructor(obj: IVillage) {
    this.username = obj.username
    this.userReference = new ReferenceWrapper(obj.userReference)
  }
}

あとは上記のVillageを初期化してstoreにsetすればちゃんと使えるようになります!

まとめ

というわけでvuexのstoreはプリミティブで持つ!というのを忘れずにというところで、
DocumentReferenceをstoreで持つためのちょっとした工夫を紹介しました。

みなさんのfirebase X nuxtライフが豊かになりますように!

最後に、ワンナイト人狼オンラインというゲームを作ってます!よかったら遊んでね!

他にもcameconoffchaといったサービスも作ってるのでよかったら使ってね!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0