データの取得
リアルタイム更新のデータの取得(querySnapshot)
custom hookで取得しやすくする
hook/useCollection.tsx
import { useEffect, useState } from "react";
import { db } from "../../firebase";
import { QueryDocumentSnapshot } from "firebase/firestore/lite";
import { onSnapshot, collection, DocumentData, CollectionReference } from "firebase/firestore";
interface Channels {
id: string;
channel: QueryDocumentSnapshot<DocumentData>;
}
const useCollection = (data: string) => {
const [documents, setDocuments] = useState<Channels[]>([]);
useEffect(() => {
let collectionRef: CollectionReference<DocumentData> = collection(db, data);
onSnapshot(collectionRef, (snapshot) => {
let results: Channels[] = [];
snapshot.docs.forEach((doc) => {
results.push({ id: doc.id, channel: doc.data() as any });
});
setDocuments(results);
});
}, [data]);
return { documents };
};
export default useCollection;
使いたい箇所
Sidebar.jsx
import React from "react";
import useCollection from "../hook/useCollection.tsx";
const Sidebar = () => {
const currentUser = useAppSelector((state) => state.currentUser);
const { documents: channels } = useCollection("channels");
return (
<div className="sidebar">
</div>
);
};
export default Sidebar;
データの作成
データの作成(collection)
Sidebar.tsx
import { collection, addDoc } from "firebase/firestore";
import React from "react";
import { auth, db } from "../../firebase.ts";
const Sidebar = () => {
const { documents: channels } = useCollection("channels");
const addChannel = async () => {
const channelName: string | null = prompt("新しいチャンネルを作成します");
if (channelName) {
await addDoc(collection(db, "channels"), {
channelName: channelName,
});
}
};
return (
<div className="sidebar">
</div>
);
};
export default Sidebar;
src/app/hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
データの作成(subCollection)
chat.tsx
import {
addDoc,
collection,
CollectionReference,
DocumentData,
onSnapshot,
serverTimestamp,
Timestamp,
} from "firebase/firestore";
import React, { useEffect, useState } from "react";
import { useAppSelector } from "../../app/hooks.ts";
import { db } from "../../firebase.ts";
interface Messages {
timestamp: Timestamp;
message: string;
user: {
uid: string;
photo: string;
email: string;
displayName: string;
};
}
const Chat = () => {
const [messages, setMessages] = useState<Messages[]>([]);
const channelName = useAppSelector((state) => state.channel.channelName);
const channelId = useAppSelector((state) => state.channel.channelId);
const currentUser = useAppSelector((state) => state.currentUser.currentUser);
const sendMessage = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
const collectionRef: CollectionReference<DocumentData, DocumentData> = collection(
db,
"channels",
String(channelId),
"messages",
);
await addDoc(collectionRef, {
message: inputText,
timestamp: serverTimestamp(),
user: currentUser,
});
};
return (
<div className="chat">
</div>
);
};
export default Chat;
src/app/hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;