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

귀여운 수달님의 프로필 이미지

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

안녕하세요, 리덕스를 통해서 좋아요 기능구현을 해보고 있는데 디스패치와 충돌이 나는것 같습니다.

해결된 질문

23.09.26 18:17 작성

·

297

1

안녕하세요, 좋은 강의 감사드립니다. 제가 좋아요 기능구현을 해보고 있는데,

 

클릭이 되면 state(clicked)를 통해 true로 만들어서 빨강색으로 만들고 1를 추가시키고 다시 클릭하면 false가 되면서 검게 되고 1을 감소하게 하는 기능을 구현하려고 하는데요. 각각 빨/검 1추가시키기는 되는데 둘이 합치려니까 1을 올리면서 리렌더링이 되고 clicked라는 스테이트가 바로 false로 초기화되버리는것 같습니다. 혹시 방법이있을까요? 뭐라고 검색해야 할지 감이 잘안잡혀서 질문남깁니다.

 

const Heart = ({ pageId, id, currentIndex, postId, }) => {
    const dispatch = useDispatch();
    const { coursePosts } = useSelector((state) => state.coursePost);
    const { clicked, setClicked } = useState(false);
    const heart = coursePosts[currentIndex].CourseReview[id].heart;
    const onClickHeart = () => {
        if (!clicked) {
            dispatch(coursePostActions.clickCourseReviewHeart({ pageId, postId }))
        } else {
            dispatch(coursePostActions.clickCourseReviewHeartAgain({ pageId, postId }))
        }
        setClicked(!clicked);
    }

    return (
        <button type="button" onClick={onClickHeart} className={clicked === true ? styles.active : ""}>
            <FontAwesomeIcon icon={faHeart} />
            <span>{heart}</span>
        </button>
    );
};

export default CourseReviewItems;
const coursePostSlice = createSlice({
    name: "coursePost",
    initialState,
    reducers: {
clickCourseReviewHeart(state, action) {
            const postIndex = state.coursePosts.findIndex((v) => v.id === Number(action.payload.pageId));
            const reviewIndex = state.coursePosts.findIndex((v) => v.id === action.payload.postId);
            state.coursePosts[postIndex].CourseReview[reviewIndex].heart += 1
        },
        clickCourseReviewHeartAgain(state, action) {
            const postIndex = state.coursePosts.findIndex((v) => v.id === Number(action.payload.pageId));
            const reviewIndex = state.coursePosts.findIndex((v) => v.id === action.payload.postId);
            state.coursePosts[postIndex].CourseReview[reviewIndex].heart -= 1
        }
}

답변 2

0

귀여운 수달님의 프로필 이미지

2023. 09. 26. 23:17

const CourseReviewItems = ({ coursePostReviewPosts, post, currentIndex, pageId, postId }) => {

    const starRendering = (star) => {

        const stars = [];
        for (let i = 0; i < star; i++) {
            stars.push(<span key={`fill_stars_${i}`}><FontAwesomeIcon icon={faStar} className={styles.fill_stars} /></span>)
        }

        for (let i = 0; i < 5 - star; i++) {
            stars.push(<span key={`empty_stars_${i}`}><FontAwesomeIcon icon={regStar} className={styles.empty_stars} /></span>)
        }

        return stars
    }


    return (
        <>
            <div className={styles.dt_review_item}>
                <div className={styles.dt_review_top}>
                    <div className={styles.dt_review_profile_cont}>
                        <figure>
                            <Image src={profileImg} alt="닉네임" />
                        </figure>

                        <div className={styles.dt_review_profile}>
                            <div className={styles.dt_review_star_cont}>
                                <div className={styles.dt_review_star}>
                                    {starRendering(coursePostReviewPosts.point)}
                                </div>
                                <span>{coursePostReviewPosts.point}</span>
                            </div>
                            <div className={styles.dt_review_txt}>
                                <span className={styles.dt_review_user}><b>{coursePostReviewPosts.User.name}</b>{`(${coursePostReviewPosts.User.id})`}</span>
                                <b> · </b>
                                <span>{coursePostReviewPosts.date}</span>
                            </div>
                        </div>
                    </div>
                </div>
                <div className={styles.dt_review_content}>
                    <p>{coursePostReviewPosts.content}</p>
                </div>

                <div className={styles.dt_review_bottom}>
                    <Heart id={post} pageId={pageId} currentIndex={currentIndex} postId={postId} />
                </div>
            </div>

        </>
    );
};

const Heart = ({ pageId, id, currentIndex, postId }) => {
    const dispatch = useDispatch();
    const { coursePosts } = useSelector((state) => state.coursePost);
    const [clicked, setClicked] = useState(false);


    const heart = coursePosts[currentIndex].CourseReview[id].heart;
    console.log(clicked)
    const onClickHeart = () => {
        // if (!clicked) {
        //     dispatch(coursePostActions.clickCourseReviewHeart({ pageId, postId }))
        //     console.log("true")

        // } else {
        //     dispatch(coursePostActions.clickCourseReviewHeartAgain({ pageId, postId }))
        //     console.log("false")

        // }
        setClicked((p) => !p);
        console.log("dfdf", clicked)
        dispatch(coursePostActions.clickCourseReviewHeart({ pageId, postId }))


    }
    console.log(clicked)
    return (
        <button type="button" onClick={onClickHeart} className={clicked === true ? styles.active : ""}>
            <FontAwesomeIcon icon={faHeart} />
            <span>{heart}</span>
        </button>
    );
};

export default CourseReviewItems;

0

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

2023. 09. 26. 19:42

setClicked((p) => !p) 하시면 됩니다.

귀여운 수달님의 프로필 이미지

2023. 09. 26. 22:53

빠른답변감사드립니다. 계속 콘솔로그 찍어보는데도 false로만 잡히네요. 제가 생각한대로 dispatch 불러오면서 함수 전체를 리렌더링시키고 그래서 초기값인 usestate(fasle)된게 계속 초기화되서 false로만 찍히는걸까요?

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

2023. 09. 26. 22:58

리액트는 리렌더링된다고 state가 초기화되지는 않습니다. 컴포넌트 자체가 없어졌다가 새로 만들어져야지만 state가 초기화됩니다.

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

2023. 09. 26. 22:59

const [ clicked, setClicked ] = useState(false);

{} 가 아니라 []입니다.

귀여운 수달님의 프로필 이미지

2023. 09. 26. 23:14

늦은시간에도 답변달아주셔서 감사합니다. 네네 오타 발견하고 [] 로 고쳐서 진행중입니다. 신기한게 dispatch 부분이 없으면 setClicked가 잘 작동하는데 dispatch랑 같이 쓰면 작동을 안합니다. 혹시나해서 setclicked다음에 console.log해보고 dispatch뒤에도 콘솔 넣어서 clicked값을 확인을 해봐도 전부다 false로만 뜨네요. 작동을 안하고있네요..

귀여운 수달님의 프로필 이미지

2023. 09. 26. 23:35

이유를 알것 같네요. Heart 가 map function 안에 있는데, dispatch를 하게되면 배열 전부가 한번 돌게되네요.

쉽게말해서 console.log(heart)를 하고 글 하나를 클릭하면 다른글들의 heart 값들도 출력이됩니다. (하트갯수는 그 누른애만 잘 작동합니다.) 현재 관련해서 setState가 작동을 잘안하는거같네요..

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

2023. 09. 27. 00:12

setClicked같은 set 시리즈는 바로 적용되는 게 아니라서 그 뒤에 console.log를 한다고 해서 값이 바뀌지 않습니다.

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

2023. 09. 27. 00:12

리액트 데브툴로 보시는 게 정확합니다.

귀여운 수달님의 프로필 이미지

2023. 09. 27. 00:15

python 위주로 머신러닝쪽 개발하다가 이번에 프론트엔드 프로젝트 하나 들어와서 하고있는데 비동기는 참 tricky하네요... 감사합니다. 한번 데브툴로 해결해보겠습니다