【Firebase】最新メッセージが表示されるよう、ローディング後、一番下の画面まで移動する
Firebase

【Firebase】最新メッセージが表示されるよう、ローディング後、一番下の画面まで移動する

作成日:2022年03月11日
更新日:2022年03月11日

前回は、画面に表示されている日付を、 SNS のように〇〇時間前にしました。

firebase-react-date-fns

【Firebase】画面に表示されている日付を、 SNSのように〇〇時間前にする

今回は、最新メッセージが表示されるよう、ローディング後、一番下の画面まで移動します。

最新のメッセージが一番下にくるよう設定しています。

image2

メッセージが増えると、

image3

下の文字が見えなくなってしまいます。

リロードすると、

image4

一番古いメッセージが一番上に来てしまいます。

こちらを、最新のメッセージが一番下に表示されるようにします。

まずは、画面の要素を参照するために、Home.tsx でuseRefを使用します。

react からuseRefをインポートしましょう。

tsx
import React, { useRef } from "react";

useRef を設定しましょう。

tsx
const bottomRef = useRef<HTMLDivElement>(null);

画面遷移させるために、react からuseLayoutEffectをインポートします。

tsx
import React, { useLayoutEffect, useRef } from "react";

useLayoutEffect内でscrollIntoViewを使い、スクロールするよう設定します。

tsx
useLayoutEffect(() => {
bottomRef?.current?.scrollIntoView();
});

メッセージ一覧の一番下に、<div ref={bottomRef}></div>を挿入します。

tsx
return (
<Box sx={{ flexGrow: 1, m: 2 }}>
{messages ? (
messages.map((message: Message) => (
<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 }}>
{time(message.createdAt)}
</Typography>
</Box>
</Box>
))
) : (
<p>メッセージが存在しません</p>
)}
<div ref={bottomRef}></div>
<MessageInput />
</Box>
);

では、動作確認しましょう。

画面をリロードすると、

image5

最新メッセージが一番下に来ています。

このままでは、メッセージ入力画面と被っており、またヘッダーが見えなくなっているので、修正しましょう。

Home.tsx のreturn下のBoxpt: 6, pb: 4を指定します。

tsx
<Box sx={{ flexGrow: 1, m: 2, pt: 6, pb: 4 }}>

Header.tsx のreturn下のBoxposition: “fixed”などを設定し、ヘッダーを固定します。

tsx
<Box
sx={{
flexGrow: 1,
position: "fixed",
top: 0,
width: "100%",
zIndex: 9999,
}}
>

では、画面リロードし、確認しましょう。

image6

最新メッセージが一番下に来て、ヘッダーも上部にあります。

試しにメッセージを送ってみると、

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

image7

今現在、入力欄にメッセージが残っているので、送信後はメッセージを消します。

MessageInput.tsx で送信後にmessageを空にします。

tsx
try {
const docRef = collection(firestore, "messages");
await addDoc(docRef, {
text: message,
createdAt: Timestamp.fromDate(new Date()),
user: {
name: profile?.name,
image: profile?.image,
uid: profile?.uid,
},
});
setMessage("");
} catch (err) {
console.log(err);
setError(true);
}

TextFieldvalueを設定します。

tsx
<TextField
size="small"
sx={{ flex: 1 }}
value={message}
onChange={(e) => setMessage(e.target.value)}
/>

では、メッセージを送信してみましょう。

image8

送信ボタンをクリックすると、

image9

入力欄のメッセージが消えました。

© 2024あずきぱんウェブスタジオ