https://nomadcoders.co/nwitter/
~3.6까지 들었는데, 이 부분은 firebase랑 연동해서 하는 작업이 많음~
CRUD = Create Read Update Delete
App.js
import React, { useEffect, useState } from 'react';
import AppRouter from 'components/Router';
import {authService} from 'fbase';
function App() {
const [init, setInit]=useState(false);
//const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userObj, setUserObj] = useState(null);
useEffect(() => {
authService.onAuthStateChanged((user) => {
if(user){
//setIsLoggedIn(true);
setUserObj(user);
/*} else {
setIsLoggedIn(false);*/
}
setInit(true);
});
}, [])
return (
<>
{init ? (
//<AppRouter isLoggedIn={isLoggedIn} userObj={userObj} />
<AppRouter isLoggedIn={Boolean(userObj)} userObj={userObj} />
) : (
"Initializing..."
)}
<footer>© {new Date().getFullYear()} Jueunkim</footer>
</>
)
};
export default App;
user가 쓴 게시물을 user가 삭제할 수 있도록 userObj를 추가했다.
추가되면서 바뀐 부분
useEffect(() => {
authService.onAuthStateChanged((user) => {
if(user){
//setIsLoggedIn(true);
setUserObj(user);
} /*else {
setIsLoggedIn(false);
}*/
setInit(true);
}
authService가 바뀐다면, user에 setUserObj를 넣는다. 로그인 되면 onAuthStateChanged가 호출되고, 로그인 한 user를 받게 된다.
어플리케이션이 시작하고 준비되면 setInit(true)로 시작한다. user를 얻어야 로그인이 되는데, 어떤 user도 받지 못하면 로그인할 수 없다. 만약 user를 얻게 되면 setUserObj를 사용한다. userObj가 없으면 로그인되지 않는다.
<AppRouter isLoggedIn={isLoggedIn} userObj={userObj} />
-> <AppRouter isLoggedIn={Boolean(userObj)} userObj={userObj} />
이 경우에는 원한다면 isloggedin을 지워도 된다. 대신 isloggedin대신에 userObj를 넣어주면 된다.
AppRouter이동 시, userObj의 값을 true,false로 바꾸어 보낸다.
Router.js
import React, { useState } from "react";
import { HashRouter as Router, Redirect, Route, Switch } from "react-router-dom";
import Auth from "../routes/Auth";
import Home from "../routes/Home";
import Profile from "routes/Profile";
import Navigation from "components/Navigation";
const AppRouter = ({ isLoggedIn, userObj }) => {
return(
<Router>
{isLoggedIn && <Navigation />}
<Switch>
{isLoggedIn ? (
<>
<Route exact path="/">
<Home userObj={userObj} />
</Route>
<Route exact path="/profile">
<Profile />
</Route>
</>
) : (
<>
<Route exact path="/">
<Auth />
</Route>
</>
)};
</Switch>
</Router>
)
};
export default AppRouter;
App.js의 설명에서 언급했지만, userObj를 넣어줌으로써 user인 경우에만 이동할 수 있도록 한다.
Home.js
import { dbService } from "fbase";
import React, { useState, useEffect } from "react";
import Nweet from "components/Nweet";
const Home = ({ userObj }) => {
const [nweet, setNweet] = useState("");
const [nweets, setNweets] = useState([]);
/*const getNweets = async () => {
const dbNweets = await dbService.collection("nweets").get();
dbNweets.forEach((document) => {
const nweetObject = {
...document.data(),
id: document.id,
};
setNweets((prev) => [nweetObject, ...prev]);
});
};*/
useEffect(() => {
/*getNweets();*/
dbService.collection("nweets").onSnapshot((snapshot) => {
const nweetArray = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setNweets(nweetArray);
});
}, []);
const onSubmit = async (event) => {
event.preventDefault();
await dbService.collection("nweets").add({
/*nweet,*/
text: nweet,
createdAt: Date.now(),
creatorId: userObj.uid,
});
setNweet("");
};
const onChange = (event) => {
const {
target: { value },
} = event;
setNweet(value);
};
return (
<div>
<form onSubmit={onSubmit}>
<input
value={nweet}
onChange={onChange}
type="text"
placeholder="What's on your mind?"
maxLength={120}
/>
<input type="submit" value="Upload" />
</form>
<div>
{nweets.map((nweet) => (
/*<div key={nweet.id}>
<h4>{nweet.text}</h4>
</div>*/
<Nweet
key={nweet.id}
nweetObj={nweet}
isOwner={nweet.creatorId === userObj.uid}
/>
))}
</div>
</div>
);
};
export default Home;
라우터에 userObj를 넣어줌으로써 Home이 userObj prop를 갖게 되었다!
Home에서는 업로드할 수 있게 한다. 이번 장에서 가장 많이 변화한 부분 인 것 같다. (이 때 업로드는 그냥 편하게 nweet이라 하겠음.)
이 때 업로드는 firestore가 database가 되어 글 쓴 것들이 올라간다.
Snapshot
lister로 Snapshot을 사용한다. Snapshot은 무언가가 일어나면(= 기본적으로 데이터베이스에 무슨 일이 있을 때), dbService.collection의 onSnpshot을 사용했다.
새로운 Snapshot을 받을 때 알리고 그 후에 state에 배열을 집어 넣는다.
snapshot 전에는 주석처리에서 볼 수 있겠지만 getNweets를 사용했다.
getNweets
collection의 nweet에서 가지고 오도록 dbService.collection의 get을 사용했다.
컴포넌트가 마운트 될 때, get을 통해서 모든 것을 가지고 왔다.
dbNweets.forEach는 nweet의 객체를 만드는 것이다. 모든 document.data를 가지고, id도 주었음!
setNweets((prev)=> [nweetObject, ..prev]); 모든 dbNweets안에 있는 모든 document.data에 대해서 모든 이전 nweets에 대해 새로 작성한 트윗과, 그 이전의 것들을 가지고 온다!
onSubmit
dbService.collection의 add를 쓰면 추가할 수 있다. 이 때 그냥 추가하는 것이 아니라 여러가지 속성을 준다. collection(=database)의 이름은 nweets이고 내가 작성한 text는 nweet(=업로드)가 되는 것!
전송할 때 userObj를 활용한 id와 시간을 함께 전송한다. (onChange는 언급하지 않겠음)
Nweet.js
import React, { useState } from "react";
import { dbService } from "fbase";
const Nweet = ({ nweetObj, isOwner }) => {
const [editing, setEditing] = useState(false);
const [newNweet, setNewNweet] = useState(nweetObj.text);
const onDeleteClick = async () => {
const ok = window.confirm("Are you sure you want to delete this nweet?");
if (ok) {
await dbService.doc(`nweets/${nweetObj.id}`).delete();
}
};
const toggleEditing = () => setEditing((prev) => !prev);
const onSubmit = async (event) => {
event.preventDefault();
await dbService.doc(`nweets/${nweetObj.id}`).update({
text: newNweet,
});
setEditing(false);
};
const onChange = (event) => {
const {
target: { value },
} = event;
setNewNweet(value);
};
return (
<div>
{editing ? (
<>
<form onSubmit={onSubmit}>
<input
type="text"
placeholder="Edit your List"
value={newNweet}
required
onChange={onChange}
/>
<input type="submit" value="Update List" />
</form>
<button onClick={toggleEditing}>Cancel</button>
</>
) : (
<>
<h4>{nweetObj.text}</h4>
{isOwner && (
<>
<button onClick={onDeleteClick}>Delete list</button>
<button onClick={toggleEditing}>Edit list</button>
</>
)}
</>
)}
</div>
);
};
export default Nweet;
컴포넌트는 두가지의 state를 가진다.
editing은 말 그대로 수정하고 있는지, 아닌지를 뜻한다.
newNweet는 input의 값을 수정할 수 있다. 이 경우엔 newNweet을 수정하는 것이다.
form을 submit할 때 dbservice가 collection을 한다. 어떤 collection에 데이터를 저장할지 지정하는 건 아주 중요!
'Web Service > React' 카테고리의 다른 글
[nextjs-blog] #3. Pre-rendering and Data Fetching (0) | 2022.01.11 |
---|---|
[nextjs-blog] #2. Assets, Metadata, and CSS (0) | 2022.01.10 |
[nextjs-blog] #1. Navigation (0) | 2022.01.08 |
[to-do-list] #2. 로그인/로그아웃 (0) | 2022.01.06 |
[to-do-list] #1. 초기 설정 (0) | 2022.01.05 |
댓글