[TIL #35 WECODE] 별점 기능 구현

Whoyoung90·2021년 4월 11일
9
post-thumbnail

210410 WECODE #35 2차 프로젝트 왓챠피디아


위코드 2차 프로젝트로 왓챠피디아의 상세페이지를 담당하였다.
이번 프로젝트를 하면서 내가 새롭게 구현한 기능이 4가지가 있다.

  • 별점 기능 구현
  • 캐러셀 구현
  • 평점 그래프 구현
  • 모달 창 구현

여기서 별점 기능을 먼저 적어보겠다.

import { FaStar } from 'react-icons/fa';

별 이미지는 react icon에 있는 <FaStar />을 사용

const [clicked, setClicked] = useState([false, false, false, false, false]);
  • Boolean값을 사용하여 [false,false,false,false,false]가 기본값이 된다.
  • 별(svg) 1개를 누르면 [true,false,false,false,false]
    2개를 누르면 [true,false,false,false,false]가 되는
    식으로 로직을 구현해보려한다. console을 꼭 찍어보도록 !
 <Stars>
        {ARRAY.map((el, idx) => {
          return (
            <FaStar
              key={idx}
              size="50"
              onClick={() => handleStarClick(el)}
              className={clicked[el] && 'yellowStar'}
            />
          );
        })}
      </Stars>
  • map함수는 배열을 받아 새로운 배열로 리턴하는 함수이기에
    별5개를 리턴하기 위해 상수 ARRAY=[0,1,2,3,4]를 선언하여 map을 돌린다.
  • <FaStar /> svg 5개가 map함수에 의해 돌아가고 클릭한 별의 인덱스 값이 el에 찍히게 된다.
    평점을 3점을 준다면 el = 3
const handleStarClick = index => {
    let clickStates = [...clicked];
    for (let i = 0; i < 5; i++) {
clickStates[i] = i <= index ? true : false;
    }
    setClicked(clickStates);
  };
  • handleStarClick 함수의 인자는 위에서 클릭한 el값을 index로 받게 된다. el = index = 3
  • for문을 돌리게 되면 i <= 3이 될때까지는 true값을 반환하게 된다.
  • 이런 과정으로 별 3점을 클릭하면 [true,true,true,false,false]이 추출되는 것이다.
  useEffect(() => {
    sendReview();
  }, [clicked]); //컨디마 컨디업

  const sendReview = () => {
    let score = clicked.filter(Boolean).length;
  };
  • filter(Boolean)을 통해 true값만 반환해줄 수 있다.
    length까지 붙여서 결국 "true=별을 클릭한 갯수"을 구현하는 것이다.

scss대신 함수형 컴포넌트

const Stars = styled.div`
display: flex;
padding-top: 5px;

& svg {
  color: gray;
  cursor: pointer;
}

:hover svg {
  color: #fcc419;
}

& svg:hover ~ svg {
  color: gray;
}

.yellowStar {
  color: #fcc419;
}
`;
  • react-icon에서 사용한 <FaStar />svg 아이콘으로 표현다는 것을 이번 기회에 알게 되었다.
  • :hover svg { color: #fcc419; } : 3번째 별을 hover해도 일단은 5개 모두 노란색일 것이다.
  • & svg:hover ~ svg { color: gray; } : hover된 별 이외에 나머지 별들(hover ~ svg)은 회색을 줌으로써 내가 원하는 별갯수 만큼 노란색을 들어올 수 있게 하였다!!
  • 앞 map함수에서 className={clicked[el] && 'yellowStar'}을 통해 클릭한 별만큼 노란색으로 남아있도록 사용한 class값이 .yellowStar { color: #fcc419; }이다.

> 함수형 컴포넌트

import React, { useState, useEffect } from 'react';
import { FaStar } from 'react-icons/fa';
import styled from 'styled-components';

const ARRAY = [0, 1, 2, 3, 4];

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

  const handleStarClick = index => {
    let clickStates = [...clicked];
    for (let i = 0; i < 5; i++) {
      clickStates[i] = i <= index ? true : false;
    }
    setClicked(clickStates);
  };

  useEffect(() => {
    sendReview();
  }, [clicked]); //컨디마 컨디업

  const sendReview = () => {
    let score = clicked.filter(Boolean).length;
    // fetch('http://52.78.63.175:8000/movie', {
    //   method: 'POST',
    //   Headers: {
    //     Authroization: 'e7f59ef4b4900fe5aa839fcbe7c5ceb7',
    //   },
    //   body: JSON.stringify({
    //     movie_id:1
    //     star: score,
    //   }),
    // });
  };

  return (
    <Wrap>
      <RatingText>평가하기</RatingText>
      <Stars>
        {ARRAY.map((el, idx) => {
          return (
            <FaStar
              key={idx}
              size="50"
              onClick={() => handleStarClick(el)}
              className={clicked[el] && 'yellowStar'}
            />
          );
        })}
      </Stars>
    </Wrap>
  );
}

export default Rating;

const Wrap = styled.div`
  display: flex;
  flex-direction: column;
  padding-top: 15px;
`;

const RatingText = styled.div`
  color: #787878;
  font-size: 12px;
  font-weight: 400;
`;

const Stars = styled.div`
  display: flex;
  padding-top: 5px;

  & svg {
    color: gray;
    cursor: pointer;
  }

  :hover svg {
    color: #fcc419;
  }

  & svg:hover ~ svg {
    color: gray;
  }

  .yellowStar {
    color: #fcc419;
  }
`;
profile
비전공으로 일식 쉐프가 되었듯, 배움에 겸손한 프론트엔드 개발자가 되겠습니다 :)

1개의 댓글

comment-user-thumbnail
2022년 5월 2일

감사합니다 많은 도움이 됐습니다!

답글 달기