[React] 별점 기능 구현하기

chaevivi·2022년 11월 23일
0


리액트로 별점 기능 구현하기

'네캔만원' 프로젝트의 맥주를 평가하는 부분에서 별점 기능이 필요해 구현하게 되었다. 리액트에서 제공하는 컴포넌트가 있어서 적용시켜 보았지만 우리가 흔히 생각하는 UX와는 다른 부분이 있어서 직접 구현하기로 했다.

구현 내용

  1. 처음에는 속이 빈 별 5개가 있다.
  2. 예를 들어, 3번째 별을 클릭하면 1, 2, 3번째 별이 속이 채워진 별로 바뀐다. (별점 3점)
  3. 다시 3번째 별을 클릭하면 1, 2, 3 번째 별이 다시 속이 빈 별로 바뀐다. (별점 3점 취소)
  4. 3번째 별까지 클릭한 상태라고 가정했을 때, 2번째 별을 클릭하면 3번째 별은 속이 빈 별로 바뀐다. (별점 3점 -> 2점 수정)
  5. 3번째 별까지 클릭한 상태라고 가정했을 때, 4번째 별을 클릭하면 4번째 별이 속이 채워진 별로 바뀐다. (별점 3점 -> 4점 수정)

소스 코드

{[1, 2, 3, 4, 5].map(el => (
  <img 
  	key={el}
  	id={el}
	className={styles.star} 
	src="/img/star-regular.png"
	alt=""
	onClick={goToFetch} />
))}
  • map 함수로 속이 빈 별 5개 출력
  • 각각의 별 id는 차례대로 숫자로 부여

const [starClick, setStarClick] = useState(null);
const [preClicked, setPreClicked] = useState(starClick);
  • starClick : 현재 클릭한 별
  • preClicked : 이전에 클릭한 별

const goToFetch = (e) => {
  e.preventDefault();
  const nowClicked = e.target.id;  // 현재 클릭한 id
  setStarClick(nowClicked);  

  if(nowClicked !== null) {  // 별이 클릭한 상태라면
    if(nowClicked > preClicked) {
      for (let i = 1; i <= nowClicked; i++) {
        const star_id = document.getElementById(i);
        star_id.src = "/img/star.png";
      }
    }
    else if(nowClicked < preClicked){
      for (let i = 1; i <= nowClicked; i++) {
        const star_id = document.getElementById(i);
        star_id.src = "/img/star.png";
      }
      for(let j = 5; j > nowClicked; j--) {
        const star_id = document.getElementById(j);
        star_id.src = "/img/star-regular.png";
      }
    }
    else {
      for (let i = 1; i <= nowClicked; i++) {
        const star_id = document.getElementById(i);
        star_id.src = "/img/star-regular.png";
      }
    }
  }
}
  • 현재 클릭한 별의 인덱스 값과 전에 클릭한 별의 인덱스 값을 비교
  • 현재 클릭한 별 > 전에 클릭한 별
    - 현재 클릭한 별의 인덱스까지 속이 채워진 별로 변경
  • 현재 클릭한 별 < 전에 클릭한 별
    - 현재 클릭한 별의 인덱스까지 속이 채워진 별로 변경
    • 전에 클릭한 별 - 현재 클릭한 별 = 나머지 별들은 속이 빈 별로 변경
  • 현재 클릭한 별 = 전에 클릭한 별
    - 현재 클릭한 별만큼 속이 빈 별로 변경

마치며

내가 생각한 코드는 조건문, 반복문이 많아서 아주 좋은 코드라고 생각되어지지는 않지만 내가 생각했던 사용자 경험에 비추어 직접 고안해냈기 때문에 배울 점이 훨씬 많았다. 조금 더 실력이 쌓이면 이 코드를 리팩토링 해보고 싶다.

profile
직접 만드는 게 좋은 프론트엔드 개발자

0개의 댓글