일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프론트엔드
- 알고리즘
- nodejs
- 백준 스택 시간초과 python
- C++
- 파이썬
- javascript
- k for k
- 안드로이드
- 리액트
- 코딩테스트
- TS
- JS
- typescript
- Python
- 자바스크립트
- stdin vs input
- NPM
- 타입스크립트
- HTML
- 스택
- react
- next Link
- Android
- 백준 스택
- firebase
- kotlin
- 최적화
- 파이어베이스
- CSS
- Today
- Total
sooleeandtomas
댓글 사용하기, 댓글 알람주기 feat. firebase realtime DB 본문
firebase에서 복합쿼리 사용하는 법
1. 색인 탭에서 -> 색인 만들기 클릭
3. 컬렉션 id, 필드 입력, 쿼리범위 : 컬렉션
4. 복합쿼리를 생성하는데 좀 시간이 오래 걸린다고 합니다. 1시간정도?
댓글 불러오기
댓글의 데이터 형태는 아래와 같습니다.
각 post_id 가 [ { }, { }, { } ] post_id에 해당하는 댓글 리스트를 가져오는 것입니다.
[
13kngsfOSNO:[{
centents: "",
id: "",
insert_dt: "",
post_id: "",
user_id: "",
user_name: "",
user_profile: "",
},{
centents: "",
id: "",
insert_dt: "",
post_id: "",
user_id: "",
user_name: "",
user_profile: "",
}]
]
redux에서 댓글 리스트 가져오기
const getCommentFB = (post_id = null) => {
if(!post_id){return}
return function(dispatch, getState, {history}){
const commentDB = firestore.collection("comment"); // 파이어베이스에서 "comment" 이름을가진 db를 찾아옵니다.
commentDB
.where("post_id", "==", post_id) // commentDB에서 "post_id" 가 post_id 와 같은 값을 찾아옵니다.
.orderBy("insert_dt", "desc") // 내림차순으로 정렬해줍니다.
.get() //데이터를 가져옵니다.
.then(docs => {
let list =[] //배열을 하나 만들어줍니다.
docs.forEach(doc=>{
list.push({...doc.data(), id: doc.id}) // id값을 같이 넣어서 배열에 {comment} 를 넣어줍니다.
// [ { comment1 }, { comment2 }, { comment3 } .... ] 이 됩니다.
})
dispatch(setComment(post_id, list)) // redux에 저장해줍니다. * post_id와 리스트를 보내줍니다.
// { [postid] : [ { coment1 }, { comment2 }, { comment3 } ... ] } 형식으로 저장해야하기 때문입니다.
}).catch(err=>{
console.log('get comment err', err);
});
}
}
dispatch - setComment 로 post_id 와 list를 전달하면
dispatch - setComment 에서 post_id : [ { } , { } ] 로 저장해줍니다.
export default handleActions(
{
[SET_COMMENT]: (state, action) => produce(state, (draft) => {
draft.list[action.payload.post_id] = action.payload.comment_list;
// 데이터 형식이 { post_id : [ {comment1}, {comment1}, {commnt3} ] } 으로 저장되어야 합니다.
})
},
initialState
);
댓글 쓰기
const addCommentFB = (post_id, contents) => {
return function(dispatch, getState, {history}){
const commentDB = firestore.collection("comment");
const user_info = getState().user.user;
let comment = {
post_id,
user_id: user_info.uid,
user_name: user_info.user_name,
user_profile: user_info.user_profile,
contents : contents,
insert_dt: moment().format("YYYY-MM-DD HH:mm"),
} //comment 데이터 형식을 설정해줍니다.
commentDB
.add(comment) // commentDB에 데이터를 넣어줍니다.
.then(doc => { //
const postDB = firestore.collection("post"); //postDB를 찾아줍니다.
const post = getState().post.list.find( l => l.id === post_id) //postDB 데이터 중에서 post_id 와 id 가 같은 데이터를 찾아줍니다.
const increment = firebase.firestore.FieldValue.increment(1); // increment를 가져옵니다.
comment = {...comment, id: doc.id} // comment에 comment.id를 저장해줍니다.
postDB
.doc(post_id) // post_id로 업데이트 할 포스트를 찾아줍니다.
.update({ comment_cnt : increment } ) // comment_cnt를 업데이트해줍니다.
.then(()=>{
dispatch(addComment(post_id, comment)); // 커맨트를 리듀서로 저장하기위해 보냅니다.
if(post){
dispatch(postActions.updatePost(post_id, { comment_cnt: parseInt(post.comment_cnt) + 1})) // 포스트 리듀서로 cnt값을 보냅니다.
}
}).catch(err => {
console.log(err);
})
}).catch(err => {
console.log(err)
})
}
}
RealTime DataBase 사용하기
firebase console에서 이번엔 realtime database 설정을 해줍니다.
만약 설정 시 싱가포르, 미국 이런데를 선택했다면 databaseURL 이 바뀌었을 겁니다.
realtime database를 사용하려 하면 아래와 같은 에러가 뜨면서 작동하지 않습니다.
이때 다시 firebase console 나의 사용자 및 권한으로 들어가서
apiKey, autodomain,
projectId,
storageBucket ...
등등의 firebase config를 복사해서 다시 나의 firebaseConfig에 붙여넣어주면 됩니다.
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import "firebase/storage";
import "firebase/database"; // 실시간 데이터는 database입니다.
const firebaseConfig = {
//생략
};
firebase.initializeApp(firebaseConfig);
const apiKey = firebaseConfig.apiKey;
const auth = firebase.auth();
const firestore = firebase.firestore();
const storage = firebase.storage();
const realtime = firebase.database();
export { auth, apiKey, firestore, storage, realtime };
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import { Badge } from "@material-ui/core"; //material ui를 사용합니다.
import NotificationsIcon from '@material-ui/icons/Notifications';
import { realtime } from "../shared/firebase"; //fire베이스에서 등록해준 realtime 불러옵니다.
const NotiBadge = props => {
const user_id = useSelector(state => state.user.user.uid);
const { _onClick } = props
const [is_read, setIsRead] = useState(true); // read: false일 경우에만 알람이 울립니다.
const notiCheck = () => { // 알람 표시를 누른 경우에는
const notiDB = realtime.ref(`noti/${user_id}`);
notiDB.update({ read: true }) // read: true로 바꿔주어 알람을 꺼줍니다.
_onClick();
}
useEffect(()=>{
const notiDB = realtime.ref(`noti/${user_id}`); // 구독 DB
notiDB.on("value", snapshot => { //구독을 켜줍니다.
setIsRead(snapshot.val().read); // firebase realtimeDB에 등록해 놓은 key값을 가져옵니다.
})
return () => notiDB.off(); // 랜더가 종료되면 구독을 종료해줍니다.
},[])
return(
<>
<Badge color="secondary" variant="dot" invisible={is_read} onClick={notiCheck}>
<!-- isvisible이 알람을 보여주는 것 -->
<NotificationsIcon/>
</Badge>
</>
)
};
NotiBadge.defaultProps = {
_onClick : () => {}
}
export default NotiBadge
noti상태를 업데이트 하는 법
const notiDB = realtime.ref(`noti/${user_id}`); // 참조할 notiDB 가져오기
notiDB.update({ read: true }) // notiDB 업데이트 해줍니다.
noti의 정보가 모여있는 news 페이지를 realtime DB의 정보를 가져와 사용할 것입니다.
이를 위해 comment를 남기는 즉시 realtime DB에 comment 관련 정보를 저장해줍니다.
redux/module/comment.js 에서 addCommentFB 함수를 수정해줍니다.
const addCommentFB = (post_id, contents) => {
return function(dispatch, getState, {history}){
const commentDB = firestore.collection("comment");
const user_info = getState().user.user;
let comment = {
post_id,
user_id: user_info.uid,
user_name: user_info.user_name,
user_profile: user_info.user_profile,
contents,
insert_dt: moment().format("YYYY-MM-DD HH:mm"),
}
commentDB
.add(comment)
.then(doc => {
const postDB = firestore.collection("post");
const post = getState().post.list.find( l => l.id === post_id)
const increment = firebase.firestore.FieldValue.increment(1);
comment = {...comment, id: doc.id}
postDB
.doc(post_id)
.update({ comment_cnt : increment } )
.then(()=>{
dispatch(addComment(post_id, comment));
if(post){
dispatch(postActions.updatePost(post_id, { comment_cnt: parseInt(post.comment_cnt) + 1}))
}
//😜 noti 여기서부터 봅니다.
const _noti_item = realtime.ref(`noti/${post.user_info.user_id}/list`).push();
// realtimeDB에 새로운 리스트를 저장할 자리를 마련해줍니다.
// 이 db는 userid로 구분을 해줍니다.
// db는 { {userid : read: false , list: [{ comment1 }, { comment2 }, { comment3 }] } }의 형태로 저장할겁니다.
_noti_item.set({ // set함수를 통해 새로운 list 아이템을 저장해줍니다.
post_id,
user_name: comment.user_name,
image_url: post.image_url,
insert_dt: comment.insert_dt,
}, err => {
if(err){
console.log("noti save error", err)
}else{
const notiDB = realtime.ref(`noti/${post.user_info.user_id}`);
notiDB.update({read: false})// 저장에 성공했다면 read : false를 통해 알람을 울려줍니다.
}
})
}).catch(err => {
console.log(err);
})
}).catch(err => {
console.log(err)
})
}
};
데이터베이스에 저장했다면 이제 New.js 페이지에서 정보를 가져와서 사용합니다.
// PostList.js
import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Grid, Image, Text } from "../elements";
import { realtime } from "../shared/firebase";
import { history } from "../redux/configureStore";
const NewsList = (props) => {
const user = useSelector(state => state.user.user);
const [noti, setNoti] = useState([]);
useEffect(()=>{
if(!user){ return };
const notiDB = realtime.ref(`noti/${user.uid}/list`); // userid에 맞는 realtimeD를가져옵니다.
const _noti = notiDB.orderByChild("insert_dt"); // 정보를 정렬해서 가져옵니다. r.db는 오름차순으로밖에 정렬이 안됩니다.
_noti.once("value", snapshot => { //한번만 가져올 것이기 떄문에 noti.on 이 아닌 noti.once로 가져옵니다.
if(snapshot.exists()){ // 정보가 있다면 : 정보.exists()의 함수로 체크합니다.
let _data = snapshot.val(); // 정보의 data를 가져옵니다.
let _noti_list = Object.keys(_data).reverse().map(s => { // 내림차순으로 재정렬해줍니다.
return _data[s];
});
setNoti(_noti_list);
}
})
},[user])
return(
<>
{noti.map((data, idx)=>(
<News key={`NEWS_${idx}`}{...data}/>
))}
</>
)
}
const News = props => {
const { image_url, user_name, post_id } = props;
return(
<Grid
_onClick={()=>{ history.push(`/postdetail/${post_id}`)}}
is_flex
justify="flex-start"
padding="30px"
>
<Image src={image_url} shape="rectangle" size="100px"/>
<Grid padding="20px">
<Text align="start"><strong>{user_name}</strong>님이 게시글에 댓글을 남겼습니다 :) !</Text>
</Grid>
</Grid>
)
}
NewsList.initialProsp = {
user_name:"",
post_id:"",
image_url:"",
}
export default NewsList
'코딩 공부 노트 > React' 카테고리의 다른 글
saga flow (0) | 2021.06.18 |
---|---|
리액트 검색엔진 최적화 하는 법 meta - tag, memo (0) | 2021.05.19 |
Infinity Scroll (Debounce & Throttle 어떤걸 쓰면 좋을까?) (0) | 2021.05.14 |
Redux 미들웨어로 saga를 써야 할까? thunk를 써야할까? (0) | 2021.05.14 |
Firebase Storage 사용 : 이미지 저장 (0) | 2021.05.13 |