인프런 커뮤니티 질문&답변

jinne님의 프로필 이미지
jinne

작성한 질문수

React로 NodeBird SNS 만들기

댓글 삭제 기능 예전에 여쭤봤었는데 추가로 여쭤봅니다 ㅠㅠ

작성

·

276

0

https://www.inflearn.com/questions/33328

이 질문을 했었는데 ㅠㅡㅠ 해결을 다시 해보려고 합니다

<코드>

<router>

<saga>

<reducer>

아 이해했습니다. 그러면 request 액션에 post Id를 넣으시고, saga, axios통해서 요청 보내신 후에 success액션에서 request액션으로부터 postId 그대로 가져와서 하시면 됩니다.

function* watchLoad(action) {

dispatch({ type: LOAD_SUCCESS, postId: action.data.postId }) // 이런 식으로  action에 들어있는 거 그대로 쓰세요.
}

이렇게 댓글을 달아주셨는데 request 액션에서 postId를 넣을 때 router 파트에서 그 부분을 찾아줘야 하는지, 혹시 그동안 수업했던 부분 중 참고할 수 있는 부분이 있는지 궁금합니다. 제가 다른 기능들을 참고하면서 여러가지 시도를 해봤었는데 ㅠㅠ 계속 오류가 나서요! postId 자체를 찾아주지 못하고 있는 상황이라고 저는 생각하고 있습니다. 

답변 6

0

jinne님의 프로필 이미지
jinne
질문자

와 진짜 감사합니다 ㅠㅠㅠㅠㅠㅠㅠㅠ!!! 드디어 해결되었어요 계속 애먹고 있었는데 ㅠㅡㅠ...... 상세 페이지까지 해결되어서 너무 기뻐요 ㅠㅠㅠㅠ 감사합니다!!! 헷갈리는 개념도 더 잡히는 것 같아요 감사합니다~~~!!! 

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아래처럼 바꾸셨으면 action.data 모양이 바뀌었습니다. 따라서 saga에서도 action.data.commentId, action.data.postId로 모양이 바뀌어야겠죠?

dispatch({
            type : REMOVE_COMMENT_REQUEST,
            data : { commentId, postId: post.id },
});

0

jinne님의 프로필 이미지
jinne
질문자

const PostCard = memo(({ post, commentOpened }) => {
    const [commentFormOpened, setCommentFormOpened] = useState(commentOpened);
    const id = useSelector(state => state.user.me && state.user.me.id);
    const dispatch = useDispatch();

    const liked = id && post.Likers && post.Likers.find(v => v.id === id);
    const postIdNum = post.id;
    const onToggleComment = useCallback(() => {
        // 펼쳐져있으면 닫고 닫혀있으면 펼치고
        setCommentFormOpened(prev => !prev);
        if (!commentFormOpened) {
            dispatch({
                type : LOAD_COMMENT_REQUEST,
                data : post.id,
            });
        }
    }, []);

    const onToggleLike = useCallback(()=> {
        if (!id) {
            return alert('로그인이 필요합니다');
        }
        // likers 안에 좋아요 누른 사람들의 배열이 들어있음
        if (liked) { //좋아요 누른 상태
            dispatch({
                type : UNLIKE_POST_REQUEST,
                data : post.id
            })
        } else { //좋아요 안 누른 상태
            dispatch({
                type : LIKE_POST_REQUEST,
                data : post.id
            })
        }
    }, [id, post && post.id, liked]);

    const onRetweet = useCallback(() => {
        if(!id){
            return alert('로그인이 필요합니다');
        }
        return dispatch({
            type : RETWEET_REQUEST,
            data : post.id,
        });
    }, [id , post && post.id]);

    const onFollow = useCallback(userId => () => {
        dispatch({
            type : FOLLOW_USER_REQUEST,
            data : userId,
        });
    }, []);

    const onUnfollow = useCallback(userId => () => {
        dispatch({
            type : UNFOLLOW_USER_REQUEST,
            data : userId,
        });
    }, []);

    const onRemovePost = useCallback(postId => () => {
        dispatch({
            type : REMOVE_POST_REQUEST,
            data : postId,
        });
    }, []);

    const onRemoveComment = useCallback(commentId => () => {
        dispatch({
            type : REMOVE_COMMENT_REQUEST,
            data : commentId
        });
    }, []);

    return (
        <CardWrapper>
            <Card
                // cover = {post.Images[0] && <img alt="example" src={`http://localhost:7070/` + post.Images[0].src}/>}
                cover={post.Images && post.Images[0] && <PostImages images={post.Images} />}
                actions = {[
                    <Icon type="retweet" key="retweet" onClick={onRetweet}/>,
                    <Icon type="heart" key="heart" theme={liked ? 'twoTone' : 'outlined'} twoToneColor="#ff7a45" onClick={onToggleLike}/>,
                    <Icon type="message" key="message" onClick={onToggleComment}/>,
                    <Popover
                        key="ellipsis"
                        content={(
                        <Button.Group>
                            {id && post.UserId === id
                            ? (
                                <>
                                <Button type="danger" onClick={onRemovePost(post.id)}>삭제</Button>
                                </>
                            )
                            : <Button>신고</Button>}
                        </Button.Group>
                        )}
                    >
                        <Icon type="ellipsis" />
                    </Popover>,
                ]}
                title = {post.RetweetId ? `${post.User.nickname}님이 리트윗 하셨습니다` : <span >{moment(post.createdAt).format('YYYY.MM.DD.')}</span>}
                //로그인을 안 했다면 버튼이 보이지 않음
                extra = {<FollowButton post = {post} onUnfollow={onUnfollow} onFollow={onFollow} />}
            >
                {post.RetweetId && post.Retweet
                ? (
                <Card cover = {post.Retweet.Images[0] && <PostImages images={post.Retweet.Images} />}>
                    <DateSpan>{moment(post.createdAt).format('YYYY.MM.DD.')}</DateSpan>
                    <Card.Meta
                        avatar = {<Link href = {{pathname : '/user', query : { id : post.Retweet.User.id } }} as = {`/user/${post.Retweet.User.id}`}><a><Avatar>{post.Retweet.User.nickname[0]}</Avatar></a></Link>}
                        title = {<Link href = {{pathname : '/post', query : { id : post.RetweetId ? post.RetweetId : post.id } }} as = {`/post/${post.RetweetId ? post.RetweetId : post.id}`}><PostCardAtag>
                        {post.Retweet.User.nickname}</PostCardAtag></Link>}
                        description = {<Link href = {{ pathname : '/post', query : { id : post.RetweetId ? post.RetweetId : post.id } }} as = {`/post/${post.RetweetId ? post.RetweetId : post.id}`}><PostCardDesAtag><PostCardContent postData={post.Retweet.content}/></PostCardDesAtag></Link>}
                    />
                </Card>
                ) : (
                    <Card.Meta
                        avatar = {<Link href = {{ pathname : '/user', query : { id : post.User.id } }} as = {`/user/${post.User.id}`}><a><Avatar>{post.User.nickname[0]}</Avatar></a></Link>}
                        title = {<Link href = {{ pathname : '/post', query : { id : post.RetweetId ? post.RetweetId : post.id } }} as = {`/post/${post.RetweetId ? post.RetweetId : post.id}`}><PostCardAtag>{post.User.nickname}</PostCardAtag></Link>}
                        description = {<Link href = {{ pathname : '/post', query : { id : post.RetweetId ? post.RetweetId : post.id } }} as = {`/post/${post.RetweetId ? post.RetweetId : post.id}`}><PostCardDesAtag><PostCardContent postData={post.content}/></PostCardDesAtag></Link>}
                    />
                )}
            </Card>
            {commentFormOpened && (
                <>
                    <CommentForm post={post}/>
                    <List
                        header={`${post.Comments ? post.Comments.length : 0} reply`}
                        itemLayout = "horizontal"
                        dataSource = {post.Comments || []}
                        renderItem = {item => (
                            <CommentWrapper>
                                <CommentStyle
                                    author = {item.User.nickname}
                                    avatar = {<Link href = {{ pathname : '/user', query : { id : item.User.id } }} as = {`/user/${item.User.id}`}><a><Avatar>{item.User.nickname[0]}</Avatar></a></Link>}
                                    content = {item.content}
                                />
                                {id && item.User.id === id
                                ?
                                <CommentRemoveBtn onClick={onRemoveComment(item.id)}>삭제</CommentRemoveBtn>
                                :
                                null}
                            </CommentWrapper>
                        )}
                    />
                </>
            )}
        </CardWrapper>
    );
});

PostCard.propTypes = {
    post : PropTypes.shape({
        User : PropTypes.object,
        content : PropTypes.string,
        img : PropTypes.string,
        createdAT : PropTypes.string,
    }),
};

export default PostCard;

전체적으로 이렇게 받아오고 있는데 윗 댓글처럼 변경하면

아예 commentId도 인식하지 못하고 있습니다. item.id로 받아와서 그런가? 라고 생각은 하지만 명확하게 해결되지는 않습니다 ㅠㅠ 그냥 commentId로만 받아왔을 때는 화면에 적용은 되지 않지만

db에서는 잘 지워집니다...! ㅠㅠ 

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

post라는 변수가 상위에 없나요? 없으시면 props를 통해서 상위 컴포넌트로부터 받아오셔야 합니다.

0

jinne님의 프로필 이미지
jinne
질문자

dispatch action에 postId를 넣어달라는 말 맞나요? 근데 commentId를 바로 가져오는거라 그런지, 거기서 post.id를 가져오지 못하는 것 같습니다

const onRemoveComment = useCallback(commentId => () => {
        dispatch({
            type : REMOVE_COMMENT_REQUEST,
            data : {
                commentId,
                postId : post.id,
            }
        });
    }, []);

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

REMOVE_POST_REQUEST 액션에 postID를 넣어주세요.

jinne님의 프로필 이미지
jinne

작성한 질문수

질문하기