https://nomadcoders.co/nwitter
트위터 클론코딩 – 노마드 코더 Nomad Coders
React Firebase for Beginners
nomadcoders.co
*노마드코더 트위터 클론코딩 강의내용을 정리한 글입니다.
**강의에서는 Firebase v8 를 사용했지만 여기서는 Firebase v9을 사용하여 구현했습니다.
// Home.js
import React, { useState } from "react";
export default function Home() {
const [nweet, setNweet] = useState("");
const onSubmitHandler = (event) => {
event.preventDefault();
};
const onChangeHandler = (event) => {
setNweet(event.target.value);
};
return (
<div>
<form onSubmit={onSubmitHandler}>
<input type="text" value={nweet} onChange={onChangeHandler} placeholder="What's on your mind?" maxLength={120} />
<input type="submit" value="Nweet" />
</form>
</div>
);
}
// fb.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
projectId: process.env.REACT_APP_PROJECT_ID,
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_APP_ID,
};
const fbApp = initializeApp(firebaseConfig);
export const fbAuth = getAuth(fbApp);
export const fbStore = getFirestore(fbApp); // 추가
https://console.firebase.google.com/project/nwitter-9aeb9/firestore/data/~2F
https://firebase.google.com/docs/firestore/quickstart#web-version-9_2
// Home.js
// ...생략
const onSubmitHandler = async (event) => {
event.preventDefault();
try {
const nweetData = {
nweet,
createdAt: new Date(),
creatorId: userInfo.uid, // App.js에서 userInfo를 가져와서 할당
};
const res = await addDoc(collection(fbStore, "nweets"), nweetData);
console.log(res);
setNweet("");
} catch (error) {
console.log(error);
}
};
// ...생략
// Home.js
// ...생략
const getNweets = async (querySnapshot) => {
try {
const tempNweets = [];
querySnapshot.docs.mapforEach((doc) => {
tempNweets.push({ id: doc.id, ...doc.data() });
});
// map구문 사용가능
// const tempNweets = querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
console.log(tempNweets);
setNweets([...tempNweets]);
} catch (error) {
console.log(error);
}
};
// ...생략
https://firebase.google.com/docs/reference/js/firestore_.timestamp
// Home.js
<div>
{nweets.map((item, idx) => (
<div key={`nweet-${idx}`}>
<h4>{item.nweet}</h4>
<span>{item.createdAt.toDate().toLocaleString()}</span> // timestamp객체 변환
</div>
))}
</div>
useEffect(() => {
onSnapshot(collection(fbStore, "nweets"), (querySnapshot) => getNweets(querySnapshot));
}, []);
const getNweets = (querySnapshot) => {
try {
const tempNweets = querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
console.log(tempNweets);
setNweets([...tempNweets]);
} catch (error) {
console.log(error);
}
};
import React from "react";
export default function Nweet({ nweet, isOwner }) {
return (
<div>
<h4>{nweet.nweet}</h4>
<span>{nweet.createdAt.toDate().toLocaleString()}</span>
{isOwner && (
<>
<button>Delete Nweet</button>
<button>Edit Nweet</button>
</>
)}
</div>
);
}
const deleteNweet = async () => {
const ok = window.confirm("Are you sure you want to delete this Nweet?");
if (ok) await deleteDoc(doc(fbStore, "nweets", nweet.id));
};
const updateNweet = async (event) => {
event.preventDefault();
updateDoc(doc(fbStore, "nweets", nweet.id), { nweet: newNweet });
toggleEditing();
};
// Nweet.js
import { deleteDoc, doc, updateDoc } from "firebase/firestore";
import React, { useState } from "react";
import { fbStore } from "../fb";
export default function Nweet({ nweet, isOwner }) {
const [editing, setEditing] = useState(false);
const [newNweet, setNewNweet] = useState(nweet.nweet);
const deleteNweet = async () => {
const ok = window.confirm("Are you sure you want to delete this Nweet?");
if (ok) await deleteDoc(doc(fbStore, "nweets", nweet.id));
};
const toggleEditing = () => setEditing((prev) => !prev);
const updateNweet = async (event) => {
event.preventDefault();
updateDoc(doc(fbStore, "nweets", nweet.id), { nweet: newNweet });
toggleEditing();
};
const onChangeHandler = (event) => {
const value = event.target.value;
setNewNweet(value);
};
return (
<div>
{editing ? (
<>
<form>
<input type="text" value={newNweet} required onChange={onChangeHandler} />
<input type="submit" value="update" onClick={updateNweet} />
</form>
<button onClick={toggleEditing}>Cancel</button>
</>
) : (
<>
<h4>{nweet.nweet}</h4>
<span>{nweet.createdAt.toDate().toLocaleString()}</span>
{isOwner && (
<>
<button onClick={deleteNweet} name="delete">
Delete Nweet
</button>
<button onClick={toggleEditing} name="edit">
Edit Nweet
</button>
</>
)}
</>
)}
</div>
);
}
[Twitter Clone Coding] #5 EDIT PROFILE (0) | 2022.11.09 |
---|---|
[Twitter Clone Coding] #4 FILE UPLOAD (2) | 2022.11.07 |
[Twitter Clone Coding] #2 AUTHENTICATION (0) | 2022.11.03 |
[Twitter Clone Coding] #1 SETUP (0) | 2022.11.01 |