チャットApp(リアルタイムデータベース)

今回はとても苦戦した、firebaseのonSnapchatを使ったリアルタイムデータベース通信の機能を追加します。これを追加すると一応の完成になります。

スクリーンショット 2020-08-25 12.51.00

onSnapshot

firebaseのonSnapshotはfirebaseの指定したデータベースを監視して変更があればそれを通知したり、変更の差分を受け取ったりできる機能です。

チャットでメッセージを書き込むとfirestoreにデータが追加されるのでonSnapshotで監視しておくと差分が発生し、通知されます。それをトリガーにして新しいチャットを読み込むことでリアルタイムに新しいメッセージを受け取ることが出来ます。

実装

最初はdatabase.tsに関数として作成しコンポーネントに読み込もうとしたのですが、上手くいきませんでした。監視するということは起動したら閉じられるまで常駐させないといけないのですが、関数で読み込むと一度実行して閉じる形になっているのだと思われます。しかし、この考察に関しては、他にも色々な要素(例えば開発環境での実行はプロジェクトの変更の差分を見て必要な部分だけをリビルドするので前のバグが残ったりなど)があるので信頼性の低い考察です。

ということでコンポーネントに直書きします。

chatroom/[roomid]/index.tsx

useEffect(() => {
   const path = location.pathname.split("/chatroom/")[1];
   const unsubscribe = FBdb.collection("chatrooms").doc(path)
   .onSnapshot(snapshots => {
       updateRoom(snapshots.data() as ChatroomType);
       scrollBottom(); 
   }, error => {
       console.log(error);
   });
   return () => unsubscribe();
}, []);

レンダリング後すぐに実行して欲しいので、useEffectに書きます。書き方は単純にコレクション、ドキュメントを指定してonSnapshotメソッドを呼びます。コールバック関数でその後の処理を記述します。
ここではindex.tsx内のroomステートにセットするupdateRoom関数とブラウザを一番下にスクロールするscrollBottom関数を書いています。これをunsubscribe変数に代入します。
最後のreturn () => unsubscribe();でコンポーネントをアンマウントした時に開放します。こうしないとページを移ったあともonSnapshotが実行され続けエラーの原因になります。

これでリアルタイムでチャットをすることが出来ます。下の動画はデモです。スマホとPCでやりとりをしています。リアルタイムにチャット出来ていることがわかると思います。

この実装に1日を費やしてやっと出来ました。今ここに書いてて一日使ってたったこれだけのコードか〜と思いました。そういうこともありますよね。

一応これで当初の目的は達成しました。

スクリーンショット 2020-08-25 14.32.39

これで完成でもいいのですが実際に使ってもらう為には最低でももう少しユーザに寄り添う必要があると思います。せっかく作ったので最低限使ってもらえるものにしたいですね。
具体的には操作の説明を入れる必要がありますし、自分のチャットルームに誰かを招待する時もボタン一つでURLをコピー出来るようにしてあげる必要があるでしょう。
またfirebaseのルールも設定しないと現状無制限にアクセス出来る状態です。

次回その辺をやって完成としたいと思います。上であげているもの以外にも変更などを加えています。詳しくはgithubを見てください。

この記事が気に入ったらサポートをしてみませんか?