후기, 리뷰에서 쓰일 별점 기능을 구현해보려고 한다.
// 5개 별점 boolean 초기 상태 설정
const [clicked, setClicked] = useState<boolean[]>([
false,
false,
false,
false,
false,
]);
const handleStarClick = (index: number): void => {
let clickStates: boolean[] = [...clicked];
for (let i = 0; i < 5; i++) {
clickStates[i] = i <= index ? true : false;
}
setClicked(clickStates);
};
<ReviewRating clicked={clicked} onStarClick={handleStarClick} />
// 별점 컴포넌트.tsx
const ReviewRating = ({ clicked, onStarClick }: RatingProps) => {
const starArray = [0, 1, 2, 3, 4];
// true의 개수를 점수로 환산
const rating = clicked.filter(Boolean).length;
return (
<div className={styles.stars}>
// 배열을 순회해서 선택이 된 값은 노란색, 아닌 값은 회색으로 표시
{starArray.map((el) => {
return (
<AiFillStar
fontSize={40}
key={el}
id={`${el}`}
onClick={() => onStarClick(el)}
className={`${clicked[el] && styles.yellowStars}`}
/>
);
})}
// 점수만큼 텍스트로 표시
<p className={styles.ratingTxt}>
{rating === 5
? "5.0"
: rating === 4
? "4.0"
: rating === 3
? "3.0"
: rating === 2
? "2.0"
: rating === 1
? "1.0"
: "0.0"}
</p>
</div>
);
};
export default ReviewRating;
.stars {
display: flex;
padding-top: 5px;
}
.stars svg {
color: gray;
cursor: pointer;
}
.stars:hover svg {
color: yellow;
}
.stars svg:hover ~ svg {
color: gray;
}
.stars .yellowStars {
color: yellow;
}