前回は、メッセージにプロフィール情報を追加し、Firestore Database に保存しました。

今回は、Firestore Database に保存しているデータを基に、React でチャット画面を作成します。

まずは、新しいユーザーを作成します。

image2

image3

ユーザー登録後、ログイン画面へ遷移できるよう、hooks フォルダの useAuth.ts にある signup 関数にリダイレクトを設定します。

const signup = (email: string, password: string) => {
  setError(null)
  createUserWithEmailAndPassword(fireauth, email, password)
    .then(res => {
      setTimeout(() => {
        navigate("/login")
      }, 2000)
    })
    .catch(err => {
      console.log(err.message)
      setError(err.message)
    })
}

ログイン後、プロフィールを登録します。

image4

メッセージを送信すると、

image5

メッセージが表示されました。

このままでは日付順にメッセージが並んでいないので、日付順に並べ替えます。

以前作成した、hooks フォルダの useFirebase.ts を開きます。

日付順に並べ替えるために、firebase/firestore から query と orderBy をインポートします。

import { collection, onSnapshot, query, orderBy } from "firebase/firestore"

useEffect 内に queryRef を作成し、query を設定します。

query の第一引数には、docRef、第二引数には、orderbyを指定します。

日付は、Firestore Database のcreatedAtで管理しているので、orderbyにはcreatedAtを指定します。

const docRef = collection(firestore, data)
const queryRef = query(docRef, orderBy("createdAt"))

onSnapshotの第一引数にdocRefを指定していましたが、queryRefへ変更します。

useEffect(() => {
  const firestore = firebaseApp.firestore
  const docRef = collection(firestore, data)
  const queryRef = query(docRef, orderBy("createdAt"))
  const unsub = onSnapshot(queryRef, snapshot => {
    let results: any = []
    snapshot.docs.forEach(doc => {
      results.push({ ...doc.data(), id: doc.id })
    })
    console.log(results)
    setDocuments(results)
  })
  return () => unsub()
}, [data])

では、ブラウザで確認しましょう。

image6

メッセージが日付順で表示されました。

次に、自分のメッセージは画面左側、相手のメッセージは画面右側になるよう修正します。

Home.tsx でprofileuidmessageの uid が等しければ、flexDirectionrow、等しくなければ、row-reverseにします。

また、メッセージにmargin-leftを設定していましたが、gapへ変更します。

<Box
  key={message.id}
  sx={{
    display: "flex",
    flexDirection:
      profile && profile.uid === message.user.uid ? "row" : "row-reverse",
    my: 2,
    gap: 2,
  }}
>
  <Box>
    <Avatar src={message.user.image ? message.user.image : ""} alt="" />
  </Box>
  <Box>
    <Typography sx={{ p: 1, background: "#dddddd", borderRadius: 1 }}>
      {message.text}
    </Typography>
    <Typography sx={{ fontSize: 12 }}>
      {format(message.createdAt.toDate(), "yyyy年MM月dd日")}
    </Typography>
  </Box>
</Box>

ブラウザで確認すると、

image7

自分のメッセージは画面左側、相手のメッセージは画面右側になりました。

ブログ一覧