rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
App.js
import { 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);
}); // 사용자 로그인 상태의 변화를 관찰한다.
}, []);
// console.log(authService.currentUser);
// setInterval(() => {
// // console.log(authService.currentUser); // 인증하는데 시간이 걸린다.
// }, 2000);
// console.log(init); // authService.onAuthStateChanged 때문에 init의 상태 값이 true로 바뀌면서 <AppRouter> 컴포넌트가 나오게 된다.
return (
<>
{init ? (
<AppRouter isLoggedIn={isLoggedIn} userObj={userObj} />
) : (
"Initializing ..."
)}
<footer>© {new Date().getFullYear()} Nwitter</footer>
</>
);
}
export default App;
Router.js
import React from "react";
import { HashRouter as Router, Route, Switch } from "react-router-dom";
import Auth from "routes/Auth";
import Home from "routes/Home";
import Profile from "routes/Profile";
import Navigation from "./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;
Home.js
// import { dbService } from "fbase";
import Nweet from "components/Nweet";
import { dbService } from "fbase";
import {
getDocs,
addDoc,
collection,
onSnapshot,
doc,
} from "firebase/firestore";
import React, { useEffect, useState } from "react";
const Home = ({ userObj }) => {
const [nweet, setNweet] = useState("");
const [nweets, setNweets] = useState([]);
// const getNweets = async () => {
// const dbnweets = await getDocs(collection(dbService, "nweets"));
// dbnweets.forEach((document) => {
// // console.log(document.data());
// const nweetObject = {
// ...document.data(),
// id: document.id,
// };
// setNweets((prev) => [nweetObject, ...prev]);
// });
// }; // 예전 방식 (snapshot을 이용한 방식이 좀 더 간편하다 , 또한 더 적게 re-render하기 때문에 더 빠르게 실행되도록 만들어 준다.)
useEffect(() => {
// getNweets(); // 예전 방식
onSnapshot(collection(dbService, "nweets"), (snapShot) => {
const nweetArray = snapShot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setNweets(nweetArray); // 더 적은 렌더링으로 데이터가 실시간으로 변한다.
});
// snapshot은 데이터베이스에 무슨일이 일어날 때, 알림을 받는다.
// 여기서는 firestore의 nweets 컬렉션에 무슨 일이 발생할 경우 콜백함수를 실행한다.
}, []);
// console.log(nweets);
const onSubmit = async (e) => {
e.preventDefault();
await addDoc(collection(dbService, "nweets"), {
text: nweet,
createdAt: Date.now(),
creatorId: userObj.uid, // 로그인할 때 유저정보를 받아온다.
});
setNweet("");
};
const onChange = (e) => {
const {
target: { value },
} = e;
setNweet(value);
};
return (
<div>
<form>
<input
type="text"
placeholder="What's on your mind"
maxLength={120}
value={nweet}
onChange={onChange}
/>
<input type="submit" value="Nweet" onClick={onSubmit} />
</form>
<div>
{nweets.map((nweet) => {
return (
<Nweet
key={nweet.id}
nweetObj={nweet}
isOwner={nweet.creatorId === userObj.uid}
/>
);
})}
</div>
</div>
);
};
export default Home;