๋๊ตฐ๊ฐ ์์ ํ๊ฑฐ๋ ์ง์ด ๋๊ธ์ด ์ค์๊ฐ์ผ๋ก ๋ํ๋๋๊ฑด ๋ณด๊ณ ์ถ์ง ์๋ค.
๋ชจ๋ ํ์ด์ง๋ ์์๊ฐ ์ค์๊ฐ์ผ ํ์๋ ์๋ค.
ํธ์์ ์์ ํ๊ณ ์ง์ฐ๋ ๊ธฐ๋ฅ์ ๋ฃ์ด ๋ณด์.
์์ผ๋ก ํธ์์ ๋ค์ด๊ฐ๋ ๋ด์ฉ์ด ๋ง์์ง ์์ ์ด๋ ํธ์ ์์ฒด๋ฅผ ์ปดํฌ๋ํธ๋ก ๋ง๋ค์ด ๋ฒ๋ฆฌ์.
import React from "react";
const Tweet = ({ tweetObj }) => (
<div>
<h4>{tweetObj.text}</h4>
</div>
);
export default Tweet;
ํธ์์ ๋ ๋๋๋ Home ํ์ด์ง์ Tweet ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ์.
//์๋ต
import Tweet from "components/Tweet";
//์๋ต
{/*DB์์ ๊ฐ์ ธ์จ ํธ์ํฐ ๋์ด*/}
<div>
{tweets.map((tweet) => (
//Tweet์ ์ปดํฌ๋ํธ๋ก ๋ง๊ณ props์ผ๋ก ๊ฐ์ ธ์จ๋ค.
//tweetObj ๋ง๋ค ๋ ๊ฐ๊ฐ์ tweet์ ํ ๋นํ id ๊ฐ์ div์ key์ ๋ฃ์ด์ฃผ์
<Tweet key={tweet.id} tweetObj={tweet} />
))}
</div>
import React from "react";
const Tweet = ({ tweetObj }) => (
<div>
<h4>{tweetObj.text}</h4>
<button>์ญ์ </button>
<button>์์ </button>
</div>
);
export default Tweet;
ํธ์์ ์์ฑํ ์ฌ๋๋ง ํด๋นํ๋ ํธ์์ ์ญ์ /์์ ํ ์ ์๊ฒ ํด์ผ ํ๋ค.
Home.js์์ userObj๋ฅผ ๋ฐ์์ค๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ด์ฉํ์ฌ ๋๊ฐ ์์ฑํ ํธ์์ธ์ง ํ์
ํ๊ณ ๊ทธ์ ๋ฐ๋ผ ์ญ์ /์์ ๋ฒํผ์ด ๋ณด์ด๊ฒ ํ๋ฉด ๋๋ค.
ํด๋นํ๋ ํธ์์ creatorId์ userObj์ uid๊ฐ ๊ฐ์ผ๋ฉด true, ๋ค๋ฅด๋ฉด false๊ฐ ๋๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ค.
isOwner={tweet.creatorId === userObj.uid}
{/*DB์์ ๊ฐ์ ธ์จ ํธ์ํฐ ๋์ด*/}
<div>
{tweets.map((tweet) => (
//Tweet์ ์ปดํฌ๋ํธ๋ก ๋ง๊ณ props์ผ๋ก ๊ฐ์ ธ์จ๋ค.
//tweetObj ๋ง๋ค ๋ ๊ฐ๊ฐ์ tweet์ ํ ๋นํ id ๊ฐ์ div์ key์ ๋ฃ์ด์ฃผ์
<Tweet
key={tweet.id}
tweetObj={tweet}
//ํด๋นํ๋ ํธ์์ creatorId์ userObj์ uid๊ฐ ๊ฐ์ผ๋ฉด true, ๋ค๋ฅด๋ฉด false๊ฐ ๋จ
isOwner={tweet.creatorId === userObj.uid}
/>
))}
</div>
import React from "react";
//isOwner ํ๋กญ ๋ฐ์์ค๊ธฐ
const Tweet = ({ tweetObj }, isOwner) => (
<div>
<h4>{tweetObj.text}</h4>
{/*ํธ์ ์ฃผ์ธ์ธ ๊ฒฝ์ฐ๋ง ์ญ์ /์์ ๋ฒํผ ๋ณด์ด๊ฒ*/}
{isOwner && (
<>
<button>์ญ์ </button>
<button>์์ </button>
</>
)}
</div>
);
export default Tweet;
์ญ์ ๋ฒํผ ํด๋ฆญ์, ๋ฐ์ํ๋ ์ด๋ฒคํธ๋ฅผ onDeleteClick ๋ฆฌ์ค๋๊ฐ ๋ฃ๊ฒ ํ์.
<button onClick={onDeleteClick}>์ญ์ </button>
onDeleteClick ๋ฆฌ์ค๋์๋ ํธ์์ ์ญ์ ํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋๋ค.
๋คํ๋จผํธ, ์ฆ ํธ์์ ์ญ์ ํ๊ธฐ ์ํด์๋ firestore์ reference์ธ delete()๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์์
import { doc, deleteDoc } from "firebase/firestore";
await deleteDoc(doc(db, "cities", "DC"));
๋จผ์ doc() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋๋น > ํธ์์ปฌ๋ ์
> ํด๋นํ๋ id ๊ฐ์ง ๋คํ๋จผํธ๋ฅผ ์ฝ ์ฐ์ด์ค์.
const tweetTextRef = doc(dbService, "tweets", `${tweetObj.id}`);
๊ทธ๋ฌ๊ณ ๋์ deleteDoc()๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํด๋นํ๋ ๋คํ๋จผํธ๋ฅผ ์ญ์ ํ๋ฉด ๋๋ค.
await deleteDoc(tweetTextRef);
import React from "react";
import { dbService } from "fbase";
import { doc, deleteDoc } from "firebase/firestore";
const Tweet = ({ tweetObj }, isOwner) => {
//๋๋น > ํธ์์ปฌ๋ ์
> ํด๋นํ๋ id ๊ฐ์ง ๋คํ๋จผํธ ์ฐ์ด์ค๊ธฐ
const tweetTextRef = doc(dbService, "tweets", `${tweetObj.id}`);
//์ญ์
const onDeleteClick = async () => {
const ok = window.confirm("์ ๋ง ์ด ํธ์์ ์ญ์ ํ์๊ฒ ์ต๋๊น?");
//console.log(ok); //treu/false ๋ฐํํจ
if (ok) {
//ํด๋นํ๋ ํธ์ ์ญ์
await deleteDoc(tweetTextRef);
} else {
console.log("์ญ์ ํ๋๋ฐ ์คํจ!");
}
};
//์์
return (
<div>
<h4>{tweetObj.text}</h4>
{/*ํธ์ ์ฃผ์ธ์ธ ๊ฒฝ์ฐ๋ง ์ญ์ /์์ ๋ฒํผ ๋ณด์ด๊ฒ*/}
{isOwner && (
<>
<button onClick={onDeleteClick}>์ญ์ </button>
<button>์์ </button>
</>
)}
</div>
);
};
export default Tweet;
๋คํ๋จผํธ, ์ฆ ํธ์์ ์์ ํ๊ธฐ ์ํด์๋ update()๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์์
import { doc, updateDoc } from "firebase/firestore";
const washingtonRef = doc(db, "cities", "DC");
// Set the "capital" field of the city 'DC'
await updateDoc(washingtonRef, {
capital: true
});
์์ ๋ฒํผ ํด๋ฆญ์ ์์ ๋ชจ๋ ํ๋ฉด์ ์ถ๋ ฅ๋ ์ ์๋๋ก ๊ธฐ๋ณธ ๊ฐ false์ธ state๋ฅผ ํ๋ ๋ง๋ ๋ค.
const [editing, setEditing] = useState(false);
์์ ๋ชจ๋๋ฉด ํธ์ ๋ด์ฉ์ ์์ ํ๋ form์ด ๋ณด์ด๊ณ , ์๋๋ฉด ๊ทธ๋ฅ ํธ์ ๋ด์ฉ์ด ๋ณด์ด๋ฉด ๋๋ค.
{editing ? (
<>
<form onSubmit={onSubmit}>
<input
value={newTweet}
required
type="text"
placeholder="์์ ํ ๋ด์ฉ์ ์
๋ ฅํ์ธ์."
onChange={onChange}
></input>
<input type="submit" value="์์ " />
</form>
<button onClick={toggleEditing}>์ทจ์</button>
</>
) : (
<>
<h4>{tweetObj.text}</h4>
{/*ํธ์ ์ฃผ์ธ์ธ ๊ฒฝ์ฐ๋ง ์ญ์ /์์ ๋ฒํผ ๋ณด์ด๊ฒ*/}
{isOwner && (
<>
<button onClick={onDeleteClick}>์ญ์ </button>
<button onClick={toggleEditing}>์์ </button>
</>
)}
์์ ๋ชจ๋์์ ์ทจ์ ๋ฒํผ ๋๋ฅด๋ฉด ๋ค์ ์๋ ํ๋ฉด์ผ๋ก ๋์๊ฐ๋๋ก onClick ์ด๋ฒคํธ๋ฅผ ๋ง๋ค๊ณ , ํธ์ ์์ ํ๊ธฐ ๋ฒํผ ํด๋ฆญ์ ์ด๋ฒคํธ๋ฅผ ๋ฆฌ์จํ๋ toggleEditing๋ฅผ ๋ค์ ํ๋ฒ ํธ์ถํ๋ค.
toggleEditing๋ setEditing์ ํ์ฌ ๊ฐ์ ๋ฐ๋ ๊ฐ์ผ๋ก ๋ฐ๊ฟ์ฃผ๋๋ก ์์ฑํ์ฌ ํ ๊ธ์ฒ๋ผ ์ฌ์ฉํ๋ฉด ๋๋ค.
//์์ ๋ชจ๋ ํ ๊ธ (ํ ๊ธ ๋ฒํผ ๋๋ฅด๋ฉด ํ์ฌ ์ํ(๊ธฐ๋ณธ false) ๋ฐ๋๋ก ๋ฐ๋
const toggleEditing = () => setEditing((prev) => !prev);
ํธ์ ๋ด์ฉ์ ์์ ํ ์ ์๋๋ก form์ ์์ฑํ๋ค.
์์ ๋ชจ๋์์ ์ฌ์ฉ์๊ฐ input์ ์
๋ ฅํ ํธ์ ๋ด์ฉ์ ์
๋ฐ์ดํธ ํ ์ ์๋๋ก onChange ์ด๋ฒคํธ๋ฅผ ๋ฃ๋ onChange ๋ฆฌ์ค๋๋ฅผ ์์ฑํ๋ค.
event.target.value๋ฅผ ๋ฐ์์ setNewTweet(value) ๋ชจ๋ํ์ด์ด๋ก ๋ณด๋ด์ด state๋ฅผ ์
๋ฐ์ดํธํ๋ฉด ๋๋ค.
const onChange = (event) => {
const {
target: { value },
} = event;
//๐ฅ ์์ ๋ชจ๋์์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ๋ input ๊ฐ์ newTweet state์ ๋ฃ๊ธฐ
setNewTweet(value);
};
์์ ๋ชจ๋ input์์ ์
๋ ฅ๋ ํธ์ ๋ด์ฉ ์
๋ฐ์ดํธํ๋ state๋ฅผ ๋ง๋ค์ด ์ฃผ์.
๊ธฐ๋ณธ ๊ฐ์ tweetObj์ text, ์ฆ db์ ์ ์ฅ๋ ๋คํ๋จผํธ(ํธ์)์ ๋ด์ฉ์ด๋ค.
5๋ฒ์์ ์
๋ฐ์ดํธํ ๋ด์ฉ์ ๋ฐ์์ ์ด state์ ๋ฃ์ด์ฃผ๋ ๊ฑฐ๋ค.
//๐ฅ ์์ ๋ชจ๋ input์์ ์
๋ ฅ๋ ํธ์ ๋ด์ฉ ์
๋ฐ์ดํธ
const [newTweet, setNewTweet] = useState(tweetObj.text);
๋ํ ์์ ๋ชจ๋์์ ์์ ํ ํ input์ submitํ๋ฉด onSubmit ๋ฆฌ์ค๋๋ updateDoc()์ผ๋ก ํธ์ ๋ด์ฉ์ ์
๋ฐ์ดํธํ๋ค.
๊ทธ๋ฌ๊ณ ๋์ setEditing() ๋ชจ๋ํ์ด์ด๋ก false๋ฅผ ๋ณด๋ด์ด ์์ ๋ชจ๋๋ฅผ ์ข
๋ฃํ๋ค.
await updateDoc(tweetTextRef, { text: newTweet });
//๐ฅ ์
๋ํ๊ณ ๋์ ์์ ๋ชจ๋ false๋ก ๋ง๋ค์ด ์ฃผ๊ธฐ
setEditing(false);
import React, { useState } from "react";
import { dbService } from "fbase";
//๐ฅ updateDoc ์ํฌํธ
import { doc, deleteDoc, updateDoc } from "firebase/firestore";
const Tweet = ({ tweetObj }, isOwner) => {
//๐ฅ ์์ ๋ชจ๋์ธ์ง ์๋์ง false/true
const [editing, setEditing] = useState(false);
//๐ฅ ์์ ๋ชจ๋ input์์ ์
๋ ฅ๋ ํธ์ ๋ด์ฉ ์
๋ฐ์ดํธ
const [newTweet, setNewTweet] = useState(tweetObj.text);
//๋๋น > ํธ์์ปฌ๋ ์
> ํด๋นํ๋ id ๊ฐ์ง ๋คํ๋จผํธ ์ฐ์ด์ค๊ธฐ
const tweetTextRef = doc(dbService, "tweets", `${tweetObj.id}`);
//์ญ์
const onDeleteClick = async () => {
const ok = window.confirm("์ ๋ง ์ด ํธ์์ ์ญ์ ํ์๊ฒ ์ต๋๊น?");
//console.log(ok); //treu/false ๋ฐํํจ
if (ok) {
//ํด๋นํ๋ ํธ์ ์ญ์
await deleteDoc(tweetTextRef);
} else {
console.log("์ญ์ ํ๋๋ฐ ์คํจ!");
}
};
//๐ฅ ์์ ๋ชจ๋ ํ ๊ธ (ํ ๊ธ ๋ฒํผ ๋๋ฅด๋ฉด ํ์ฌ ์ํ(๊ธฐ๋ณธ false) ๋ฐ๋๋ก ๋ฐ๋
const toggleEditing = () => setEditing((prev) => !prev);
//๐ฅ ์์ ๋ชจ๋์์ ํธ์ ์์ ํ ํผ ์๋ฐํด์ ํธ์ ๋ด์ฉ ์
๋ฐ์ดํธํ๊ธฐ
const onSubmit = async (event) => {
event.preventDefault();
const ok = window.confirm("์ ๋ง ์ด ํธ์์ ์์ ํ์๊ฒ ์ต๋๊น?");
if (ok) {
await updateDoc(tweetTextRef, { text: newTweet });
//๐ฅ ์
๋ํ๊ณ ๋์ ์์ ๋ชจ๋ false๋ก ๋ง๋ค์ด ์ฃผ๊ธฐ
setEditing(false);
}
};
const onChange = (event) => {
const {
target: { value },
} = event;
//๐ฅ ์์ ๋ชจ๋์์ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ๋ input ๊ฐ์ newTweet state์ ๋ฃ๊ธฐ
setNewTweet(value);
};
return (
<div>
{/*์์ ๋ชจ๋ ๋ฒํผ ํด๋ฆญ๋ ๊ฑฐ๋ฉด(true) ์์ ํ ํผ ๋ณด์ฌ์ฃผ๊ณ : ์๋๋ฉด(false) ํธ์ ๋ด์ฉ ๋ณด์ฌ์ฃผ๊ธฐ*/}
{editing ? (
<>
<form onSubmit={onSubmit}>
<input
value={newTweet}
required
type="text"
placeholder="์์ ํ ๋ด์ฉ์ ์
๋ ฅํ์ธ์."
onChange={onChange}
></input>
<input type="submit" value="์์ " />
</form>
<button onClick={toggleEditing}>์ทจ์</button>
</>
) : (
<>
<h4>{tweetObj.text}</h4>
{/*ํธ์ ์ฃผ์ธ์ธ ๊ฒฝ์ฐ๋ง ์ญ์ /์์ ๋ฒํผ ๋ณด์ด๊ฒ*/}
{isOwner && (
<>
<button onClick={onDeleteClick}>์ญ์ </button>
<button onClick={toggleEditing}>์์ </button>
</>
)}
</>
)}
</div>
);
};
export default Tweet;