ํธ์์ ์์ฑํ์ฌ db์ create ํ๋ ๊ฒ์ ์๋ฃํ์ผ๋ ์ด์ ํ์ด์ด์คํ ์ดdb์์ ์์ฑํ ํธ์์ ๊ฐ์ ธ์ read! ์ฝ์ด๋ณด์!
firebase/firestore๋ก ๋ถํฐ query์ getDocs๋ฅผ import ํ๋ค.import {
collection,
addDoc,
serverTimestamp,
//๊ฐ์ ธ์ค๊ธฐ
query,
getDocs,
} from "firebase/firestore";
useState()๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ ํธ์์ ๊ฐ์ ธ์ค๋ ์คํ
์ดํธ๋ฅผ ๋ง๋ ๋ค.๋ฐฐ์ด(array)๋ก ์ค์ ํ์ฌ ์์ฑํ ํธ์ ๋ฐ์ดํฐ๋ค์ด ๋ฐฐ์ด์ ๋ค์ด๊ฐ ์ ์๊ฒ ํ์.//๐ฅ์์ฑํ ํธ์ ๊ฐ์ ธ์ค๊ธฐ: ๊ธฐ๋ณธ ๊ฐ์ ๋น ๋ฐฐ์ด
const [tweets, setTweets] = useState([]);
useEffect(fn, []);๋ฅผ ์ฌ์ฉํ์ฌ ํธ์ ๋ด์ฉ๋ค์ ๊ฐ์ ธ์ค์.getTweets์ ๋ง๋ค๊ณ ์ด ํจ์๋ฅผ ํธ์ถํ์.async๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๊ฐ๋ณ ํจ์๋ก ๋ฐ์ผ๋ก ๋นผ์ ๋ง๋ ํ, useEffect()์์ ํธ์ถํ๊ธฐ ์ํด์์ด๋ค.useEffect(() => {
getTweets();
}, []);
์ฉ์ด ์๊ณ ๋์ด๊ฐ๊ธฐ
- ๋ง์ดํธ(mount)
: ํ์ผ์์คํ ๊ตฌ์กฐ ๋ด์ ์๋ ์ผ๋ จ์ ํ์ผ๋ค์ ์ฌ์ฉ์๋ ์ฌ์ฉ์ ๊ทธ๋ฃน๋ค์ด ์ด์ฉํ ์ ์๋๋ก ๋ง๋๋ ๊ฒ
์ฌ๊ธฐ์ ์ฌ์ฉํ firestore์ ๋ฉ์๋
getDocs()๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ QuerySnapshot์ผ๋ก ๋ฐํํ๋ค.
- getDocs๋ promise๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์
async,await์ ์ฌ์ฉํ์.
QuerySnapshot ํด๋์ค
- QuerySnapshot์๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ํ๋ด๋ 0๊ฐ ์ด์์ DocumentSnapshot ๊ฐ์ฒด๊ฐ ํฌํจ๋์ด ์๋ค.
- ๋คํ๋จผํธ๋, docs ์์ฑ์ ํตํด
๋ฐฐ์ด๋ก ์ก์ธ์คํ๊ฑฐ๋ /forEach ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๊ฑฐํ ์ ์๋ค.- ๋ฌธ์์ ์๋ empty ๋ฐ size ์์ฑ์ ํตํด ๊ฒฐ์ ํ ์ ์๋ค.
const getTweets = async () => {
/*1. DB์์ ์ปฌ๋ ์
๊ฐ์ ธ์ค๊ธฐ
dbService์ ์๋ tweets ์ปฌ๋ ์
์ ๊ฐ์ ธ์ค๋ ์ฟผ๋ฆฌ ๋ง๋ค๊ธฐ*/
const q = query(collection(dbService, "tweets"));
/*2. ์ปฌ๋ ์
์ ๋คํ๋จผํธ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ
- ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ QuerySnapshot์ผ๋ก ๋ฐํํ๋ฉด tweets ์ปฌ๋ ์
์ document๋ค์ ์ป๋๋ค.
- ๋ฐ๋ผ์ querySnapshot์ tweets ์ปฌ๋ ์
์ document๋ค์ ๋ชจ์๋์ ๋ฐฐ์ด์ด๋ค.*/
const querySnapshot = await getDocs(q);
//3. ๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๋์ด
querySnapshot.forEach((document) => {
/*๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๋์ดํ ๋ {data, id} ์ค๋ธ์ ํธ ํํ๋ก ๋์ดํ์.
- document์ data๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด data() ๋ฉ์๋ ์ฌ์ฉ
- ํธ์ ํ๋์ฉ ๋์ด ํ ๋ ์ธ key ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ id ํ ๋น*/
const tweetObj = {
...document.data(),
id: document.id,
};
//console.log(tweetObj);
//- setTweets() ๋ชจ๋ํ์ด์ด๋ก ์ด์ tweets(prev)์ ๋ํด, ์๋ก์ด ๋ฐฐ์ด(์๋ก ์์ฑํ ํธ์๊ณผ, ...๊ทธ ์ด์ ๊ฒ๋ค)์ ๋ฆฌํดํด์ฃผ์.
setTweets((prev) => [tweetObj, ...prev]);
});
};
๋จผ์ ํ์ด์ด์คํ ์ด์์ ์ฌ์ฉํ ์ปฌ๋ ์
์ ๊ฐ์ ธ์์ผ ํ๋ค.
query()๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ, dbService์ ์๋ tweets ์ปฌ๋ ์
์ ๋ํ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์.
์ปฌ๋ ์
์ ๊ฐ์ ธ์์ผ๋ tweets ์ปฌ๋ ์
์ document๋ค์ ๊ฐ์ ธ์ค์.
getDocs()๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.q)๋ฅผ ๋ณด๋ด๊ณ , ์ด ๊ฐ์ querySnapshot๋ณ์๋ก ํ ๋นํ์.getDocs()์ ํธ์ถํ ๋๋ await์ ์ฌ์ฉํ์ฌ ๋๊ธฐ์ฒ๋ฆฌ ํด์ฃผ์.๋ชจ๋ ๋คํ๋จผํธ๋ฅผ ๊ฐ์ง ๋ฐฐ์ด์ธ querySnapshot์์ ๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๋์ดํ๊ธฐ ์ํด์๋ forEach๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๊ฐ์ ธ์ฌ ๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ธ์ ํธ ํํ๋ก ๋์ด๋๊ฒ ํ์.
{๋คํ๋จผํธ์ data, id}data() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ ธ์ค๋ฉด ๋๋ค.console.log(tweetObj);๋ฅผ ํด๋ณด๋ฉด ์ปฌ๋ ์
์ ๋ค์ด ์๋ ๋คํ๋จผํธ๋ค์ด ๊ฐ๊ฐ์ ์ค๋ธ์ ํธ๋ก ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. 
setTweets() ๋ชจ๋ํ์ด์ด๋ก state๋ฅผ ์
๋ฐ์ดํธ ํด์ฃผ์. ๊ทธ๋์ผ ๋ฐฉ๊ธ ์ด ํธ์๋ tweets state์ ๋ค์ด๊ฐ๋ค....๋ฅผ ์ฌ์ฉํ์ฌ, ์ด์ tweets(prev)์ ๋ํด, ์๋ก์ด ๋ฐฐ์ด(์๋ก ์์ฑํ ํธ์๊ณผ, ...๊ทธ ์ด์ ๊ฒ๋ค)์ ๋ฆฌํดํด์ฃผ์.tweets state๋ ๋ฐฐ์ด์ด๊ธฐ ๋๋ฌธ์, ๋ฐฐ์ด์ item์ ๋์ดํ๊ธฐ ์ํด map() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์.<div>
{tweets.map((tweet) => (
//tweetObj ๋ง๋ค ๋ ๊ฐ๊ฐ์ tweet์ ํ ๋นํ id ๊ฐ์ div์ key์ ๋ฃ์ด์ฃผ์
<div key={tweet.id}>
<h4>{tweet.tweet}</h4>
</div>
))}
</div>import React, { useEffect, useState } from "react";
import { dbService } from "fbase";
import {
collection,
addDoc,
serverTimestamp,
query,
getDocs,
} from "firebase/firestore";
const Home = () => {
//ํ์์ ํธ์ ๋ด์ฉ ์์ฑํ๋ ํผ
const [tweet, setTweet] = useState("");
//0. ์์ฑํ ํธ์ ๊ฐ์ ธ์ค๊ธฐ: ๊ธฐ๋ณธ ๊ฐ์ ๋น ๋ฐฐ์ด
const [tweets, setTweets] = useState([]);
const getTweets = async () => {
/*1. DB์์ ์ปฌ๋ ์
๊ฐ์ ธ์ค๊ธฐ
dbService์ ์๋ tweets ์ปฌ๋ ์
์ ๊ฐ์ ธ์ค๋ ์ฟผ๋ฆฌ ๋ง๋ค๊ธฐ*/
const q = query(collection(dbService, "tweets"));
/*2. ์ปฌ๋ ์
์ ๋คํ๋จผํธ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ
- ์ฟผ๋ฆฌ๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ QuerySnapshot์ผ๋ก ๋ฐํํ๋ฉด tweets ์ปฌ๋ ์
์ document๋ค์ ์ป๋๋ค.
- ๋ฐ๋ผ์ querySnapshot์ tweets ์ปฌ๋ ์
์ document๋ค์ ๋ชจ์๋์ ๋ฐฐ์ด์ด๋ค.*/
const querySnapshot = await getDocs(q);
//3. ๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๋์ด
querySnapshot.forEach((document) => {
/*๊ฐ๊ฐ์ ๋คํ๋จผํธ๋ฅผ ๋์ดํ ๋ {data, id} ์ค๋ธ์ ํธ ํํ๋ก ๋์ดํ์.
- document์ data๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด data() ๋ฉ์๋ ์ฌ์ฉ
- ํธ์ ํ๋์ฉ ๋์ด ํ ๋ ์ธ key ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ id ํ ๋น*/
const tweetObj = {
...document.data(),
id: document.id,
};
//- setTweets() ๋ชจ๋ํ์ด์ด๋ก ์ด์ tweets(prev)์ ๋ํด, ์๋ก์ด ๋ฐฐ์ด(์๋ก ์์ฑํ ํธ์๊ณผ, ...๊ทธ ์ด์ ๊ฒ๋ค)์ ๋ฆฌํดํด์ฃผ์.
setTweets((prev) => [tweetObj, ...prev]);
});
};
//4. ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋๋ฉด useEffect()์ฌ์ฉ
useEffect(() => {
getTweets();
}, []);
const onSubmit = async (event) => {
event.preventDefault();
//ํธ์ํ๊ธฐ ๋๋ฅด๋ฉด ์๋ก์ด document ์์ฑํ๊ธฐ
try {
const docRef = await addDoc(collection(dbService, "tweets"), {
tweet, // tweet(๋คํ๋จผํธ์ key): tweet(value๋ก tweet state ๊ฐ)
createdAt: serverTimestamp(), //Date.now(),๋ก ํด๋ ๋์ง๋ง ์ด์ ์๋๊ฑฐ ํจ ์จ๋ณด์(ํ์์กด ๋๋ถ์3 = ์์ธ๋ก ์ค์ ๋์ด ์์)
});
console.log("Document written with ID: ", docRef.id);
} catch (error) {
console.error("Error adding document: ", error);
}
//state ๋น์์ form ๋น์ฐ๊ธฐ
setTweet("");
};
const onChange = (event) => {
const {
target: { value },
} = event;
setTweet(value);
//console.log(tweet);
};
return (
<>
<div>
<form onSubmit={onSubmit}>
<input
type="text"
placeholder="๋ฌด์จ ์ผ์ด ์ผ์ด๋๊ณ ์๋์?"
maxLength={120}
value={tweet}
onChange={onChange}
/>
<input type="submit" value="ํธ์ํ๊ธฐ" />
</form>
</div>
{/*DB์์ ๊ฐ์ ธ์จ ํธ์ํฐ ๋์ด*/}
<div>
{tweets.map((tweet) => (
//tweetObj ๋ง๋ค ๋ ๊ฐ๊ฐ์ tweet์ ํ ๋นํ id ๊ฐ์ div์ key์ ๋ฃ์ด์ฃผ์
<div key={tweet.id}>
<h4>{tweet.tweet}</h4>
</div>
))}
</div>
</>
);
};
export default Home;