별점 기능 구현하기

이동환·2021년 1월 24일
4

TIL

목록 보기
62/74

별점 기능 구현하기

꼭 한번 구현해보고 싶었던 기능이었는데, 내가 맡은 역할이 아니여서 못했습니다. 그래도 한번 꼭 해보고 싶었기에, 쉬는 시간에 코드를 보고 공부하고, 혼자 만들어봤습니다.

만들면서 신기했던 부분은 on 으로 시작하는 이벤트가 생각보다 많다였습니다. 항상 많이 썼던 이벤트는 onClick, onChange 였는데, 처음으로 onMouseEnter,onMouseLeave를 사용해봤습니다.

아래 코드는 최상위 컴포넌트입니다.

// App.js
import React, { useState } from 'react';
import Stars from './RatingIcon';

function App() {

  const [rating, setRating] = useState(0);
  const [hoverRating, setHoverRating] = useState(0);

  const onMouseEnter = (index: number) => setHoverRating(index);
  // 마우스가 별 위에 올라가면 스테이트를 변경.
  const onMouseLeave = () => setHoverRating(0);
  // 마우스가 별 밖으로 나가면 스테이트를 0으로 변경.
  const onSaveRating = (index: number) => setRating(index);
  // 클릭시, 별 인덱스를 스테이트에 저장.

  return (
    <div>
      {[1, 2, 3, 4, 5].map((idx) => {
        return (
          <Stars
            index={idx}
            rating={rating}
            hoverRating={hoverRating}
            onMouseEnter={onMouseEnter}
            onMouseLeave={onMouseLeave}
            onSaveRating={onSaveRating}
          />
        );
      })}
    </div>
  );
}

export default App;

아래코드는 Stars.tsx 입니다.

// Stars.tsx
import React, { useMemo } from 'react';
import StarIcon from './StarIcon';

interface Props {
  index: number; 
  rating: number;
  hoverRating: number; 
  onMouseEnter: (index: number) => void;
  onMouseLeave: () => void;
  onSaveRating: (index: number) => void;
}

const Stars = (props: Props) => {
  const {
    index, 
    rating,
    hoverRating,
    onMouseEnter,
    onMouseLeave,
    onSaveRating,
  } = props;

  const fillColor = useMemo(() => {
    if (hoverRating >= index) { 
      return "#ffdb58";    // #ffdb58 === 노란색
    } else if (!hoverRating && rating >= index) {
      return "#ffdb58";    // #ffdb58 === 노란색
    }
    return "#dcdcdc";      // #dcdcdc === 회색
  }, [rating, hoverRating, index]); 

  return (
    <div 
      onMouseEnter={() => onMouseEnter(index)}
      onMouseLeave={() => onMouseLeave()}
      onClick={() => onSaveRating(index)}>
      <StarIcon fillColor={fillColor} />
    </div>
  )
};

export default Stars;

마지막 컴포넌트는 최하위 컴포넌트이고, 별모양 svg입니다.

import React from 'react'; 
import { ReactComponent as StarSvg } from '../../images/review_star_full.svg'; 
// svg를 이미지 폴더 안에 있는 파일로 저장했다는 가정하에 import.

interface Props {
  fill: string
}

const StarIcon = ({ fillColor = "#dcdcdc" }: Props) => {

  return (
  <div>
    <StarSvg style={{ marginRight: '3px' }}fill={fillColor} />
  </div>
  )
}

export default StarIcon; 

fill은 svg에서만 사용가능한 녀석입니다. MDN

profile
UX를 개선하는것을 즐기고 새로운것을 배우는것을 좋아하는 개발자입니다.

0개의 댓글