그룹의 게시글의 댓글 질문합니다 ///////
358
0
https://www.inflearn.com/questions/33679
전에 답변주신 덕분에 ㅠㅠ ♡.. LOAD_MAIN_POSTS_REQUEST 게시물로드하기 성공했어요~!
그룹에 속한 게시물로 구조를 바꾸어준 후,
댓글 불러오기 LOAD_COMMENTS_REQUEST에 네트워크탭에 Request URL 에 전과 같은 undefined 오류가 나는 것을 확인했습니다
코드수정 후, 네트워크탭에서 성공의 200표시가 떳습니다.!
그런데 리덕스 데브툴즈에는 LOAD_COMMENTS_FAILURE가 뜨고 화면에서도 댓글이 보이지않았어요...
타입에러인 것을 확인했습니다,
강의하신 mainPosts의 data구조를 (어느그룹에 속한 게시물인지 데이터를보내기위해)
data에 gpostId와 content로 나누어놨었어요

그래서인지 findIndex함수가 작동하지 않는것을 확인하고,
리듀서에서 mainPosts의 배열을 뽑아내기위해 ----> mainPosts.content로 수정했습니다.

< post.js / reducers/ front >
// 댓글 불러오기
case LOAD_COMMENTS_SUCCESS: {
// console.log("state.mainPosts.content",state.mainPosts.content);
const postIndex = state.mainPosts.content.findIndex(v => v.id === action.data.postId);
// console.log("postIndex",postIndex);
const post = state.mainPosts[postIndex];
// console.log("post",post);
const Comments = action.data.comments;
// console.log("Comments",Comments);
const mainPosts = [...state.mainPosts.content];
// console.log("mainPosts",mainPosts);
mainPosts[postIndex] = { ...post, Comments };
// console.log("new : ",mainPosts[postIndex]);
return {
...state,
mainPosts,
};
}
reducer / console.log

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
이렇게 수정해주니 리덕스 데브툴즈에서도 LOAD_COMMENTS_SUCCESS
가 떳고 네트워크탭에서도 GET 방식으로 댓글이 잘 받아와지는 것을 확인할수있었어요.!
그런데 화면에서는 다른화면으로 넘어가서 원하는 결과가 나오지 않아요...ㅠㅠ
오류또한 발견핧수없었습니다.
^ 결론 :
댓글버튼을 클릭하면 dispatch로 LOAD_COMMENTS_REQUEST가 실행되고
컴포넌트<ContentForm> 에서 { post } 프롭값에 db.Comment 테이블에서 Comments 배열이 불러와졌었는데,,
post를 콘솔로 확인해보면 Comments 배열이 불러와지지 않아요,,,,

post.Comments로 결과를 화면에 나타나게 했는데 값이 불려와지지 않는게,,
왜그런지 알고싶습니다.ㅠㅠ
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
< post.js / sagas / front >
// 댓글 불러오기
function loadCommentsAPI(postId) {
return axios.get(`/post/${postId}/comments`);
}
function* loadComments(action) {
try {
const result = yield call(loadCommentsAPI, action.data);
yield put({
type: LOAD_COMMENTS_SUCCESS,
data: {
postId: action.data,
comments: result.data,
},
});
} catch (e) {
console.error(e);
yield put({
type: LOAD_COMMENTS_FAILURE,
error: e,
});
}
}
function* watchLoadComments() {
yield takeLatest(LOAD_COMMENTS_REQUEST, loadComments);
}
< ContentForm.js / Component / front >
const ContentForm = ({post}) => {
const [commentFormOpened, setCommentFormOpened] = useState(false);
const [commentText, setCommentText ] = useState('');
const { me } = useSelector(state => state.user);
const { commentAdded, isAddingComment, mainPosts } = useSelector(state => state.post);
const dispatch = useDispatch();
const liked = me && post.Likers && post.Likers.find(v => v.id === me.id);
//댓글창토글
const onToggleComment = useCallback(() => {
setCommentFormOpened(prev => !prev);
if (!commentFormOpened) {
// 댓글창 켤때 불러오기
dispatch({
type: LOAD_COMMENTS_REQUEST,
data: post.id,
});
}
}, []);
// 댓글
const onChangeComment = useCallback((e) => {
setCommentText(e.target.value);
}, []);
// 댓글올리기 사이클
const onSubmitComment = useCallback((e) => {
e.preventDefault();
if(!me){
return alert('로그인이 필요합니다.');
}
return dispatch({
type: ADD_COMMENT_REQUEST,
data:{
postId: post.id,
content: commentText,
},
});
}, [me && me.id, commentText]);
// 댓글 성공시, 빈텍스트로
useEffect(() => {
setCommentText('');
},[commentAdded === true]);
// 댓글삭제하기
const onRemoveComments = useCallback(userId => () => {
alert('댓글을 삭제하시겠습니까?');
if(me.id === post.User.id)
dispatch({
type: REMOVE_COMMENT_REQUEST,
data: userId,
});
});
// 댓글 변수선언
var listIndex;
// 게시글 삭제
const onRemovePost = useCallback(userId => () => {
if(me.id === post.User.id)
alert('게시물을 삭제하시겠습니까?');
dispatch({
type: REMOVE_POST_REQUEST,
data: userId,
});
if(me.id !== post.User.id)
alert('다른 사용자의 게시물은 삭제할 수 없습니다.');
});
// 좋아요 토글
const onToggleLike = useCallback(() => {
if (!me) {
return alert('로그인이 필요합니다!');
}
if (liked) { // 좋아요 누른 상태
dispatch({
type: UNLIKE_POST_REQUEST,
data: post.id,
});
} else { // 좋아요 안 누른 상태
dispatch({
type: LIKE_POST_REQUEST,
data: post.id,
});
}
}, [me && me.id, post && post.id, liked]);
return(
<>
<div className="postbox">
<div className="contBox">
<p>{post.User.nickname} 님의 게시물 - 좋아요 : {post.Likers.length } </p>
<PostImages images={post.Images} />
<div>{post.content}</div>
</div>
<div className="btnsbox">
<button type="button" className="commentBtn" value={commentFormOpened} onClick={onToggleComment} />
{ liked ? <button type="button" className="likeBtnred" onClick={onToggleLike} /> :
<button type="button" className="likeBtnline" onClick={onToggleLike} /> }
<button type="button" className="removeBtn" onClick={onRemovePost(post.id)} />
{commentFormOpened===true &&
<form className="commentbox" onSubmit={onSubmitComment}>
<textarea className="comment" value={commentText} onChange={onChangeComment} />
<button type="primary" htmltype="submit" className="combtn" loading={isAddingComment} >COMMENT</button>
</form>
}
{/* 댓글올라갈부분 */}
{commentFormOpened===true && (
<div style={{display:"inline-block", width:"100%"}}>
<p style={{marginLeft:"10px"}}>{commentAdded ? '댓글' + post.Comments.length : '댓글'+ '0'}</p>
<div className="comline"></div>
{console.log("mainPosts.content???: ",mainPosts.content,"post???: ",post)}
{(()=>{
if(post.Comments){
listIndex = post.Comments.map((el)=>
(
<li style={{listStyle:"none", display:"inline-block", clear:"both"}} >
{console.log("el",el)}
{el.User.nickname} : {el.content}
{ el.UserId === me.id ?
<button type="button" className="remove" onClick={onRemoveComments(post.id)} > REMOVE </button>
: "" }
</li>
)
)
}
return(
<ul>
{listIndex}
</ul>
);
})()}
</div>
)
}
</div>
</div>
</>
);
};
ContentForm.propTypes={
post: PropTypes.shape({
User: PropTypes.object,
content: PropTypes.string,
createdAt: PropTypes.string,
}),
};
export default ContentForm;
< post.js / routes / back >
// 댓글불러오기
router.get('/:id/comments', async (req, res, next) => {
try {
const post = await db.Post.findOne({ where: { id: req.params.id } });
if (!post) {
return res.status(404).send('포스트가 존재하지 않습니다........');
}
const comments = await db.Comment.findAll({
where: {
PostId: req.params.id,
},
order: [['createdAt', 'ASC']],
include: [{
model: db.User,
attributes: ['id', 'nickname'],
}],
});
res.json(comments);
} catch (e) {
console.error(e);
next(e);
}
});
답변 5
0
아, 용량때문에 따로 불러오는 경우에는 액션을 하나 더 만들고, 리듀서에서도 객체 속성 하나 만들어서 거기에 불러오시고 그 때는 게시글 객체 안에 Comments가 안 들어있으니 리듀서에서 방금 만든 속성 가져오셔야 합니다.
{ model: Comment,
include: [{ model: User }],
}
이렇게 include한 모델 안에서 한 번 더 include하시면 됩니다.
0
지니
댓글버튼을 누르면 dispatch LOAD_COMMENTS_REQUEST로 불러오고싶은건데,,
애초에 게시물불러오기할때 댓글도같이불러오게 하면 용량문제때문에 그렇게 하시지 않았나요??..
그럼 질문을 바꿔서,,
게시물 불러올때 include 로 Comment 해주고 콘솔로 확인해보니 제대로 불러와지긴하는데
Comment 안에 User 의 정보를 같이 담아서 불러오고싶은데 그건 어떻게 하나요?
UserId 만나오고 User. nickname을 구하고싶습니다.
- Comments: Array(3)
- 0:
- PostId: 1
- UserId: 2
- content: "귀여워요~"
- createdAt: "2020-04-22T10:58:46.000Z"
- id: 2
- updatedAt: "2020-04-22T10:58:46.000Z"
// 게시물'들' 불러오기
router.get('/:id', async (req, res, next) => { // GET /api/posts/100/개발자
try {
const gpost = await db.Gpost.findOne({ where: { id: req.params.id } });
if (!gpost) {
return res.status(404).send('포스트가 존재하지 않습니다.!!!!');
}
const posts = await db.Post.findAll({ // api/posts/1/comments
where: {
GpostId: req.params.id,
},
include: [{
model: db.User,
attributes: ['id', 'nickname'],
},{
model: db.Image,
},{
model: db.Comment,
},{
model: db.User,
through: 'Like',
as:'Likers',
attributes:['id'],
}],
order: [['createdAt', 'DESC']], // DESC는 내림차순, ASC는 오름차순
});
res.json(posts);
} catch (e) {
console.error(e);
next(e);
}
});
// 댓글불러오기
router.get('/:id/comments', async (req, res, next) => { // api/post/1/comments
try {
const post = await db.Post.findOne({ where: { id: req.params.id } });
if (!post) {
return res.status(404).send('포스트가 존재하지 않습니다........');
}
const comments = await db.Comment.findAll({
where: {
PostId: req.params.id,
},
order: [['createdAt', 'ASC']],
include: [{
model: db.User,
attributes: ['id', 'nickname'],
}],
});
res.json(comments);
} catch (e) {
console.error(e);
next(e);
}
});
0
게시글 불러올 때 include Comment도 하셔야 속성에 Comments 추가됩니다.
0
지니
< post.js / routes / back > 댓글 불러오는 router에 include Comment 해주어야하나요??
0
include Comment가 제대로 되어있나요??
next 10 이상에서는 redux dev tool 구동이 안되나요?
세션 갱신 문의 건
배포 진행 후 Highlight updates components render 표시
똑같은 기능을 하는 테이블
관계형
프론트 서버를 이용하지 않는경우
인피니트 스크롤링 사용시 오류
계속 이런에러가 떠서 해결하기는 했는데 어떤 의미인지 모르겠습니다.
req.user가 언제 생성되나요??
Cannot read property 'id' of null 에러
리트윗한 게시글 불러오는 sequelize
result.data에서 images인 이유
takeLatest에 대한 질문입니다.
프론트에서 express를 사용하지 않을때 동적라우팅
getInitialProps가 클라이언트에서 수행되는 이유?
리로드하면 팔로우 언팔로우 값이 초기화 되는 문제입니다.
스타일드 컴포넌트와 className을 통한 스타일 적용의 차이에 대해 궁금합니다
할인 쿠폰 사용이 안되는되요 (848-f9af83f183e3)
nodejs mvc 패턴
사용하고 보니, 람다 구성이 궁금합니다!
제로초님
새로고침 로그인 풀림 문제.
안녕하세요. 강의 너무 감사합니다
제로초님