firestore便利だけど、getしか使ったことなかった。。 onSnapshotを使うと、変更されたデータを受け取れるので、試してみたときの備忘録。
ドキュメントはこれをみた。
・Cloud Firestore でリアルタイム アップデートを入手する | Firebase
使い方
こんな感じ。
// 対象のquery const query = db.collection("...").orderBy("createAt", "desc"); // リッスンの開始 this.unset = query.onSnapshot(snapshot => { snapshot.docChanges().forEach((change: DocumentChange<DocumentData>) => { // 変更のタイプ console.info(`*** change: type=${change.type}`); // 対象のドキュメント。変更の場合は、変更後 console.info(`*** change: data=${JSON.stringify(change.doc.data(), null, 2)}`); // refに対する変更後のindex。削除時は-1 console.info(`*** change: newIndex=${change.newIndex}`); // refに対する変更前のindex。追加時は-1 console.info(`*** change: oldIndex=${change.oldIndex}`); if (change.type === "added") { // 追加時 } else if (change.type === "modified") { // 変更時 } else if (change.type === "removed") { // 削除時 } }); }); // リッスンをやめる。返ってきた関数を呼び出すとデタッチする this.unset()
この例は、collection
だけど、collectionGroup
やdoc
でも同じ感じのよう。
ハマった点: リッスン開始すると対象すべてがadded
snapshot.docChanges()
を呼び出すと、
・変更を受け取る対象が全ドキュメントになり、
・さらに、最初はaddedされる
ドキュメントには、
と書かれるけど、件数が多いとちょっと困る。。
「初期表示は10件で、そのあとは変更を受け取りたい」。。
なので、whereやendBeforeなどを使って、範囲を絞り込む必要がある。
// 初期表示分の取得 const initQuery = db.collection("...").orderBy("createAt", "desc").limit(10); const initdata = await initQuery.get(); // 最後のデータを取得 const lastData = this.getLastData(initdata); // 中身は略 // 最後のデータ以降をリッスン const query = db.collection("...").orderBy("createAt", "desc").endBefore(lastData.createAt); this.unset = query.onSnapshot(snapshot => { snapshot.docChanges().forEach((change: DocumentChange<DocumentData>) => { // 略 }); });
以上!!
【PR】これをつかって、こんなのつくりました!
よかったら、遊んでみてください(´ω`)