일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 백준
- 디자인 패턴
- react
- 프로그래머스 자바
- 자바 공부
- react firebase
- Java
- 자바
- 코딩테스트 고득점 Kit
- 리액트
- 프로그래머스
- 컴퓨터 네트워크
- websocket
- 장고
- JavaScript
- codesandbox
- 코딩테스트 고득점 Kit 완전탐색
- 리액트 훅
- useEffect
- 프로그래머스 완전탐색
- design pattern
- vanillaJS
- React JS
- useState
- 프로그래밍 언어론
- react hook
- 자바스크립트
- 데이터모델링과마이닝
- 코틀린
- NextJS
- Today
- Total
기록하는 개발자
[React, Firebase] TwitterCloneCoding 2.0 New Tweet 작성 후 database에 저장하기 본문
[React, Firebase] TwitterCloneCoding 2.0 New Tweet 작성 후 database에 저장하기
밍맹030 2021. 10. 12. 20:52< firebase의 database 사용 >
cloue firestore 의 database는 NoSQL database 이다.
-규칙이 적고 유연하다는 장점이 있으나 이로 인해 sql의 자율성에 비해 제한사항이 있다는 단점 존재
특징
-collection 이라는 것을 가진다. 이는 컴퓨터의 폴더와 같은 역할
-document : 컴퓨터에 있는 문서와 비슷하며 필드, value, uid 등을 가진다.
< tweet 두 개 입력 후 화면 >
< fBase.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_API_AUTH_DOMAIN,
projectId: process.env.REACT_APP_API_PROJECT_ID,
storageBucket: process.env.REACT_APP_API_STORAGE_BUCKET,
messagingSenderId: process.env.REACT_APP_API_MESSAGING_SENDER_ID,
appId: process.env.REACT_APP_API_APP_ID,
};
initializeApp(firebaseConfig);
export const authService = getAuth();
export const dbService = getFirestore();
- db 사용을 위해 firebase/firestore를 import 해준다.
< App.js >
import React, {useEffect, useState} from 'react';
import AppRouter from "./Router";
import { authService } from "../fBase";
import {onAuthStateChanged} from '@firebase/auth';
function App() {
const [init, setInit]=useState(false);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userInfo, setUserInfo] = useState(null);
useEffect(()=>{
onAuthStateChanged(authService, (user) => {
if(user!==null) {
setIsLoggedIn(true);
setUserInfo({user});
}
else setIsLoggedIn(false);
setInit(true);
});
},[]);
return (
<>
{init ? <AppRouter isLoggedIn={isLoggedIn} userInfo={userInfo}/> : "Initializing..."}
<footer>© twitter {new Date().getFullYear()}</footer>
</>
);
}
export default App;
1.
const [userInfo, setUserInfo] = useState(null);
- 사용자 객체를 저장할 userInfo 변수를 null로 초기화한다.
2.
useEffect(()=>{
onAuthStateChanged(authService, (user) => {
if(user!==null) {
setIsLoggedIn(true);
setUserInfo({user});
}
else setIsLoggedIn(false);
setInit(true);
});
},[]);
- user 객체가 존재할 경우 userInfo 변수를 user 객체로 초기화 한다.
3.
return (
<>
{init ? <AppRouter isLoggedIn={isLoggedIn} userInfo={userInfo}/> : "Initializing..."}
<footer>© twitter {new Date().getFullYear()}</footer>
</>
);
- AppRouter에 isLoggedIn과 함께 user 객체를 가진 변수 userInfo를 보낸다.
< Router.js >
import React from 'react';
import {Redirect, 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, {userInfo})=>{
const flag=isLoggedIn[Object.keys(isLoggedIn)[0]];
return(
<Router>
{flag&&<Navigation/>}
<Switch>
{flag? (
<>
<Route exact path="/"><Home userInfo={isLoggedIn.userInfo}/></Route>
<Route exact path="/profile"><Profile /></Route>
<Redirect from="*" to="/" />
</>
) : (
<>
<Route exact path="/"><Auth /></Route>
<Redirect from="*" to="/" />
</>
)}
</Switch>
</Router>
);
}
export default AppRouter;
1.
const AppRouter = (isLoggedIn, {userInfo})=>{
- App.js 로부터 넘겨바든 isLoggedIn과 userInfo 객체
2.
<Switch>
{flag? (
<>
<Route exact path="/"><Home userInfo={isLoggedIn.userInfo}/></Route>
<Route exact path="/profile"><Profile /></Route>
<Redirect from="*" to="/" />
</>
) : (
<>
<Route exact path="/"><Auth /></Route>
<Redirect from="*" to="/" />
</>
)}
</Switch>
- login이 true인 경우의 라우팅에서 Home component에 userInfo를 전달한다.
< Home.js >
import { dbService } from "fBase";
import React, { useEffect, useState } from "react";
import { collection, addDoc, query, onSnapshot, orderBy, serverTimestamp } from '@firebase/firestore'
import Tweet from "../components/Tweet";
const Home = ({userInfo}) => {
const [tweet, setTweet] = useState('');
const [tweets, setTweets] = useState([]);
useEffect(() => {
const q = query(collection(dbService, 'tweets'), orderBy('createdAt', 'desc'))
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const nextTweets = querySnapshot.docs.map((document) => {
return {
id: document.id,
...document.data(),
}
})
setTweets(nextTweets);
})
return () => {
unsubscribe();
}
}, [])
const OnSubmit = async (e) => {
e.preventDefault()
const docRef = await addDoc(collection(dbService, 'tweets'), {
text : tweet,
createdAt: serverTimestamp(),
creatorId : userInfo[Object.keys(userInfo)[0]].uid,
})
console.log('Document written with ID: ', docRef.id);
setTweet('');
}
const OnChange = (e) => {
const { target: { value } } = e
setTweet(value);
}
return (
<div>
<form onSubmit={OnSubmit}>
<input type="text" placeholder="What's on your mind?" maxLength={120} onChange={OnChange} value={tweet} />
<input type="submit" value="Nweet" />
</form>
<div>
{tweets.map((tweet) => (
<Tweet key={tweet.id}
tweetObj={tweet}
isOwner={tweet.creatorId===userInfo[Object.keys(userInfo)[0]].uid}
/>
))}
</div>
</div>
)
}
export default Home;
1.
const Home = ({userInfo}) => {
const [tweet, setTweet] = useState('');
const [tweets, setTweets] = useState([]);
- Routes.js로부터 userInfo 객체를 받는다.
tweet useState : 새로운 값(tweet value)을 입력하여 Database에 넣는 useState
tweets useState : Database에서 값을 가져오기 위한 useState
- tweets 는 빈 배열로 초기화한다. 이에 database에서 값들을 불러올 때 database collection의 Document를 하나씩 가져와서 배열안에 넣어 저장하고 화면으로 불러온다.
- database에서 document를 가져오기 위해서는 collection에서 get method를 사용한다.
2.
const OnSubmit = async (e) => {
e.preventDefault()
const docRef = await addDoc(collection(dbService, 'tweets'), {
text : tweet,
createdAt: serverTimestamp(),
creatorId : userInfo[Object.keys(userInfo)[0]].uid,
})
setTweet('');
}
- tweet을 작성하고 submit 을 하면 해당 tweet의 내용(text), 작성된 시간(createdAt), 작성자의 id(creatorId)가 database에 저장된다.
- 새 tweet을 database에 저장한 후 tweet form을 비워준다.
3.
const OnChange = (e) => {
const { target: { value } } = e
setTweet(value);
}
- value가 form에 입력되면 해당 event를 감지하여 tweet state 를 value로 초기화한다.
4. 실시간으로 데이터를 데이터베이스에서 가져오기
공식 문서 link : Collection QuerySnapshot onSnapshot
useEffect(() => {
const q = query(collection(dbService, 'tweets'), orderBy('createdAt', 'desc'))
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const nextTweets = querySnapshot.docs.map((document) => {
return {
id: document.id,
...document.data(),
}
})
setTweets(nextTweets);
})
return () => {
unsubscribe();
}
}, [])
q : createdAt 항목에 따라 내림차순으로 dbService(firebase db)로부터 tweet를 가져와 query로 저장한다.
unsubscrib : onSnapshot을 통해 db에 무슨 일이 있을 때 알림을 받는다.
nextTweets : querySnapshot 객체를 map을 통해 순회하며 id와 data를
- 새로운 snapshot을 받을 때 id와 doc.data를 가지는 nextTweets라는 배열을 만든다.
- 후에 tweets배열을 nextTweets 배열로 초기화한다.
- return 내부에서는 tweets배열을 이용하여 Tweet component를 만든다.
5.
return (
<div>
<form onSubmit={OnSubmit}>
<input type="text" placeholder="What's on your mind?" maxLength={120} onChange={OnChange} value={tweet} />
<input type="submit" value="Nweet" />
</form>
<div>
{tweets.map((tweet) => (
<Tweet key={tweet.id}
tweetObj={tweet}
isOwner={tweet.creatorId===userInfo[Object.keys(userInfo)[0]].uid}
/>
))}
</div>
</div>
)
}
- tweets 배열을 map으로 순회하며 Tweet component를 생성한다.
→ 각 tweet 마다 id, tweet(text 내용), userId를 가지며 Tweet component에서는 각 tweet에 대한 수정과 삭제가 가 다루어진다.
'Web > React' 카테고리의 다른 글
[React, Firebase] TwitterCloneCoding 3.0 File Upload, Delete file (0) | 2021.10.17 |
---|---|
[React, Firebase] TwitterCloneCoding 2.1 Tweet 삭제, 수정 (4) | 2021.10.12 |
[React, Firebase] TwitterCloneCoding 1.0 Authentication-Google 로그인 (0) | 2021.10.12 |
[React, Firebase] TwitterCloneCoding 0.1 router 설정 (0) | 2021.10.11 |
[React, Firebase] TwitterCloneCoding 0.0 초기 환경 설정 및 firebase 설치 (0) | 2021.10.11 |