1. 페이지 링크 연결하기
- 목록 페이지에서 _onClick 넘겨주기
// PostList.js
import React from "react";
import {useSelector, useDispatch} from "react-redux";
import Post from "../components/Post";
import {actionCreators as postActions} from "../redux/modules/post";
import InfinityScroll from "../shared/InfinityScroll";
import {Grid} from "../elements";
const PostList = (props) => {
const dispatch = useDispatch();
const post_list = useSelector((state) => state.post.list);
const user_info = useSelector((state) => state.user.user);
const is_loading = useSelector((state) => state.post.is_loading);
const paging = useSelector((state) => state.post.paging);
const {history} = props;
React.useEffect(() => {
if(post_list.length === 0){
dispatch(postActions.getPostFB());
}
}, []);
return (
<React.Fragment>
<Grid bg={"#EFF6FF"} padding="20px 0px">
{/* <Post/> */}
<InfinityScroll
callNext={() => {
dispatch(postActions.getPostFB(paging.next));
}}
is_next={paging.next ? true : false}
loading={is_loading}
>
{post_list.map((p, idx) => {
if (p.user_info.user_id === user_info?.uid) {
return (
<Grid
bg="#ffffff"
margin="8px 0px"
key={p.id}
_onClick={() => {
history.push(`/post/${p.id}`);
}}
>
<Post key={p.id} {...p} is_me />
</Grid>
);
} else {
return (
<Grid
key={p.id}
bg="#ffffff"
_onClick={() => {
history.push(`/post/${p.id}`);
}}
>
<Post {...p} />
</Grid>
);
}
})}
</InfinityScroll>
</Grid>
</React.Fragment>
);
}
export default PostList;
- Grid에 onClick() 속성을 추가하여 눌렀을 때 상세 페이지로 이동하기
import React from "react";
import styled from "styled-components";
const Grid = (props) => {
const { is_flex, width, margin, padding, bg, children, center, _onClick } = props;
const styles = {
is_flex: is_flex,
width: width,
margin: margin,
padding: padding,
bg: bg,
center: center,
};
return (
<React.Fragment>
<GridBox {...styles} onClick={_onClick}>{children}</GridBox>
</React.Fragment>
);
};
Grid.defaultProps = {
chidren: null,
is_flex: false,
width: "100%",
padding: false,
margin: false,
bg: false,
center: false,
_onClick: () => {}
};
const GridBox = styled.div`
width: ${(props) => props.width};
height: 100%;
box-sizing: border-box;
${(props) => (props.padding ? `padding: ${props.padding};` : "")}
${(props) => (props.margin ? `margin: ${props.margin};` : "")}
${(props) => (props.bg ? `background-color: ${props.bg};` : "")}
${(props) =>
props.is_flex
? `display: flex; align-items: center; justify-content: space-between; `
: ""}
${(props) => props.center? `text-align: center;`: ""}
`;
export default Grid;
2. 리덕스 연결하기
- 리덕스에 데이터 가져오기
import React from "react";
import Post from "../components/Post";
import CommentList from "../components/CommentList";
import CommentWrite from "../components/CommentWrite";
import {useSelector} from "react-redux";
const PostDetail = (props) => {
const id = props.match.params.id;
const user_info = useSelector((state) => state.user.user);
const post_list = useSelector(store => store.post.list);
const post_idx = post_list.findIndex(p => p.id === id);
const post = post_list[post_idx];
return (
<React.Fragment>
<Post {...post} is_me={post.user_info.user_id === user_info.uid}/>
<CommentWrite/>
<CommentList/>
</React.Fragment>
)
}
export default PostDetail;
3. 파이어 스터어에서 데이터 가져오기
더보기
👉 [링크를 타고 들어온다면...]
우리가 만든 사이트에 게시글 1개 링크를 타고 들어온다고 생각해볼까요? 😖
: 앗, 파이어 스토어에서 데이터 가져오는 건... 목록 페이지인데?
맞아요! 그럴 때는 데이터 가진 게 없으니 보여줄 게 없죠.
이럴 때는 해당 게시글 id를 이용해서 게시글 정보 하나만 호다닥 가져오게 합시다!
- 만약 리덕스에 데이터가 없으면?? 단일 데이터를 가져오자!
import React from "react";
import Post from "../components/Post";
import CommentList from "../components/CommentList";
import CommentWrite from "../components/CommentWrite";
import { Button, Text, Grid } from "../elements";
import { useSelector } from "react-redux";
import { firestore } from "../shared/firebase";
const PostDetail = (props) => {
const id = props.match.params.id; // 파라미터로 넘어온 params의 id를 불러온다.
const post_list = useSelector((state) => state.post.list); // 게시물 목록
const user_info = useSelector((state) => state.user.user); // 사용자 정보
const is_login = useSelector((state) => state.user.is_login); // 로그인 정보
// 상세 페이지의 게시물 정보를 불러온다.
const post_idx = post_list.findIndex((p) => p.id === id);
const post_data = post_list[post_idx];
// === const post = post_list.find(p => p.id === id)
const [post, setPost] = React.useState(post_data ? post_data : null);
const { history } = props;
React.useEffect(() => {
if (post) {
// 포스트 정보가 있을 경우 안불러 온다.
return;
}
// 단일 데이터 가져오기
const postDB = firestore.collection("post");
postDB
.doc(id)
.get()
.then((doc) => {
// 형식 맞추기
let _post = doc.data();
let post = Object.keys(_post).reduce(
(acc, cur) => {
if (cur.indexOf("user_") !== -1) {
return {
...acc,
user_info: { ...acc.user_info, [cur]: _post[cur] },
};
}
return { ...acc, [cur]: _post[cur] };
},
{ id: doc.id, user_info: {} }
);
setPost(post);
});
});
// 로그인 안했을 경우 상세 페이지 볼 수 없게
if (!is_login) {
return (
<Grid margin="100px 0px" padding="16px" center>
<Text size="32px" bold>
앗! 잠깐!
</Text>
<Text size="16px">로그인 후에만 글을 쓸 수 있어요!</Text>
<Button
_onClick={() => {
history.replace("/login");
}}
>
로그인 하러가기
</Button>
</Grid>
);
}
return (
<React.Fragment>
{post && (
<Post {...post} is_me={post.user_info.user_id === user_info.uid} />
)}
<CommentWrite />
<CommentList />
</React.Fragment>
);
};
export default PostDetail;
4. firestore 복합 쿼리 쓰기
더보기
👉 [다음 시간을 위한 준비예요!]
복합쿼리는 설정하고 반영되기까지 시간이 꽤 걸리거든요! 다음 강의 가기 전, 미리 해두고 갈게요. 😉
복합쿼리가 뭐냐구요?
복합쿼리는 firestore에서 한 콜렉션의 여러 필드를 한 쿼리로 묶을 때 필요한 거예요.
→ 여러 필드 내용을 가지고 쿼리를 쓰고 싶을 때 쓴다!
- 대시보드 설정하기
- 복합 쿼리 쓰는 방법 미리보기!!
const getCommentFB = (post_id) => {
return function (dispatch) {
console.log("in get comment fb");
firestore
.collection("comment")
**.where("post_id", "==", post_id)
.orderBy("insert_dt", "desc")**
.get()
.then((docs) => {
let _list = [];
docs.forEach((doc) => {
_list.push({ ...doc.data(), id: doc.id });
});
dispatch(setComment(_list, post_id));
})
.catch((err) => {
console.log("get comment fb err :::", err);
});
};
};
5. 로그인을 안했을 경우 상세 페이지 띄우지 않고 알림창 띄우기
const is_login = useSelector((state) => state.user.is_login); // 로그인 정보
// postDetail.js
// 로그인 안했을 경우 상세 페이지 볼 수 없게
if (!is_login) {
return (
<Grid margin="100px 0px" padding="16px" center>
<Text size="32px" bold>
앗! 잠깐!
</Text>
<Text size="16px">로그인 후에만 글을 쓸 수 있어요!</Text>
<Button
_onClick={() => {
history.replace("/login");
}}
>
로그인 하러가기
</Button>
</Grid>
);
}
또는
옵셔널 체이닝을 사용하면 된다.
A?.B일 경우 A의 값이 없으면 B를 불러오지 않아서 오류가 발생하지 않는다.
return (
<React.Fragment>
{post && (
<Post {...post} is_me={post.user_info.user_id === user_info?.uid} />
// user_info?.uid : 옵셔널 체이닝을 사용하면 user_info에 값이 있을 경우 uid를 불러온다.
)}
<CommentWrite />
<CommentList />
</React.Fragment>
);
'항해 중 > 5주차 리액트 심화반' 카테고리의 다른 글
4주차 - 댓글 알림 뱃지 만들기 (0) | 2021.12.03 |
---|---|
4주차 - 댓글 작성하기 (0) | 2021.12.02 |
4주차 - 무한 스크롤 (0) | 2021.12.02 |
3주차 - Debounce, Throttle (0) | 2021.12.01 |
2주차 - 로그인 유지하기 / 로그아웃 구현하기 / 퀴즈 (0) | 2021.11.30 |
댓글