inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

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

해결된 질문

363

귀여운 수달

작성한 질문수 2

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
        }
}

react redux node.js express next.js

답변 2

0

귀여운 수달

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

제로초(조현영)

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

0

귀여운 수달

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

0

제로초(조현영)

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

0

제로초(조현영)

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

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

0

귀여운 수달

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

0

귀여운 수달

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

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

0

제로초(조현영)

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

0

제로초(조현영)

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

0

귀여운 수달

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

넥스트 버젼 질문

0

78

2

로그인시 401 Unauthorized 오류가 뜹니다

0

90

1

무한 스크롤 중 스크롤 튐 현상

0

176

1

특정 페이지 접근을 막고 싶을 때

0

103

2

createGlobalStyle의 위치와 영향범위

0

96

2

인라인 스타일 리렌더링 관련

0

92

2

vsc 에서 npm init 설치시 오류

0

148

2

nextjs 15버전 사용 가능할까요?

0

160

1

화면 새로고침 문의

0

122

1

RTK에서 draft, state 차이가 있나요?

0

154

2

Next 14 사용해도 될까요?

0

452

1

next, node 버전 / 폴더 구조 질문 드립니다.

0

349

1

url 오류 질문있습니다

0

211

1

ssh xxxxx로 우분투에 들어가려니까 port 22: Connection timed out

0

375

1

sudo certbot --nginx 에러

0

1280

2

Minified React error 콘솔에러 (hydrate)

0

470

1

카카오 공유했을 때 이전에 작성했던 글이 나오는 버그

0

247

1

프론트서버 배포 후 EADDRINUSE에러 발생

0

329

1

npm run build 에러

0

519

1

front 서버 npm run build 중에 발생한 에러들

0

382

1

서버 실행하고 브라우저로 들어갔을때 404에러

0

338

2

css 서버사이드 랜더링이 적용되지 않아서 문의 드립니다.

0

289

1

팔로워 3명씩 불러오고 데이터 합쳐주는걸로 바꾸고 서버요청을 무한으로하고있습니다.

0

240

2

해시태그 검색에서 throttle에 관해 질문있습니다.

0

202

1