こんにちは。virapture株式会社のもぐめっとです。
こんな格好してるので前世はきっと狛犬でした。しらんけど。
今回は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を準備します。
declare type DocumentReference = import('firebase/app').default.firestore.DocumentReference
declare interface IReferenceWrapper {
readonly reference: DocumentReference
}
declare type FirestoreDocumentReference = DocumentReference | IReferenceWrapper
今回はVillageというエンティティを用意し、ユーザの情報を格納しているとします。
declare interface IVillage {
readonly username: string
readonly userReference: FirestoreDocumentReference
}
そして、今回の肝となるDocumentReferenceをプリミティブで持つラッパーを準備します。
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を使ってエンティティとなるクラスを作ります。
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ライフが豊かになりますように!
最後に、ワンナイト人狼オンラインというゲームを作ってます!よかったら遊んでね!
他にもcameconやoffchaといったサービスも作ってるのでよかったら使ってね!