inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

React로 NodeBird SNS 만들기

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

326

jinne

작성한 질문수 17

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 자체를 찾아주지 못하고 있는 상황이라고 저는 생각하고 있습니다. 

react javascript

답변 6

0

jinne

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

0

제로초(조현영)

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

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

0

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

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를 넣어주세요.

next 10 이상에서는 redux dev tool 구동이 안되나요?

0

272

1

세션 갱신 문의 건

0

482

7

배포 진행 후 Highlight updates components render 표시

0

445

1

똑같은 기능을 하는 테이블

0

447

4

관계형

0

312

2

프론트 서버를 이용하지 않는경우

1

299

3

인피니트 스크롤링 사용시 오류

0

278

0

계속 이런에러가 떠서 해결하기는 했는데 어떤 의미인지 모르겠습니다.

0

433

2

req.user가 언제 생성되나요??

0

330

2

Cannot read property 'id' of null 에러

0

332

1

리트윗한 게시글 불러오는 sequelize

0

252

1

result.data에서 images인 이유

0

281

2

takeLatest에 대한 질문입니다.

1

342

2

프론트에서 express를 사용하지 않을때 동적라우팅

0

501

6

getInitialProps가 클라이언트에서 수행되는 이유?

0

258

1

리로드하면 팔로우 언팔로우 값이 초기화 되는 문제입니다.

0

445

2

스타일드 컴포넌트와 className을 통한 스타일 적용의 차이에 대해 궁금합니다

0

585

2

할인 쿠폰 사용이 안되는되요 (848-f9af83f183e3)

0

365

1

nodejs mvc 패턴

0

975

4

사용하고 보니, 람다 구성이 궁금합니다!

0

266

1

제로초님

0

445

1

새로고침 로그인 풀림 문제.

0

247

1

안녕하세요. 강의 너무 감사합니다

0

157

1

제로초님

0

170

1