search
LoginSignup
0

More than 1 year has passed since last update.

posted at

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

こんにちは。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といったサービスも作ってるのでよかったら使ってね!

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
What you can do with signing up
0