이 코드는 백엔드와의 데이터 통신을 고려하지 않고 짜여진 코드입니다.

 

백엔드와의 데이터 통신을 고려하여 짜여진 코드는 추후 별점 그래프와 함께 추가될 예정입니다.

 

즉, 이 코드는 순수 별점기능만을 보여줍니다.

 

 

 

기능은 총 3가지가 있습니다.

 

1. 별을 클릭하면 별점이 매겨지는 기능(마우스 클릭)

2.같은 별점을 다시 클릭하면 취소하기가 되는 기능 ex) 별점 3점을 누른 후 다시 3점을 누르면 별이 모두 회색으로 변합니다.

3.마우스 Hover기능 (마우스 클릭으로 별점 4점을 줬어도 마우스 Hover시 1점~5점 자유롭게 이동가능)

 

 

 

 

<StarRating.js>

import React, { Component } from 'react';
import EachStar from './EachStar/EachStar';
import './StarRating.scss';

export default class StarRating extends Component {
  constructor() {
    super();
    this.state = {
      rateValue: [false, false, false, false, false],
      hoverRateValue: [false, false, false, false, false],
      isHover: false,
    };
  }

  handleStarClick = clickedIndex => {
    const prevRateValue = [...this.state.rateValue];
    const isClickedStarActive = prevRateValue[clickedIndex];
    const isNextStarActive = prevRateValue[clickedIndex + 1];

    if (isClickedStarActive && isNextStarActive) {
      prevRateValue.fill(false, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }

    if (isClickedStarActive) {
      prevRateValue.fill(false, 0, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }

    if (!isClickedStarActive) {
      prevRateValue.fill(true, 0, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }
  };

  handleStarMousehover = hoveredIndex => {
  
    const prevRateValue = [...this.state.hoverRateValue];
    const isClickedStarActive = prevRateValue[hoveredIndex];
    const isNextStarActive = prevRateValue[hoveredIndex + 1];

    if (isClickedStarActive && isNextStarActive) {
      prevRateValue.fill(false, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }

    if (isClickedStarActive) {
      prevRateValue.fill(false, 0, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }

    if (!isClickedStarActive) {
      prevRateValue.fill(true, 0, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }
  };

  handleStarMouseout = () => {

    this.setState({
      isHover: false,
      hoverRateValue: [false, false, false, false, false],
    });
  };

  checkIsActive = star => {
    if (this.state.isHover) {
      if (this.state.hoverRateValue[star]) {
        return 'activeStar';
      }

      return 'inactiveStar';
    }

    if (this.state.rateValue[star]) {
      return 'activeStar';
    }

    return 'inactiveStar';
  };

  render() {
    const starArray = [0, 1, 2, 3, 4];

    return (
      <>
        <div className="starList">
          {starArray.map((star, index) => {
            return (
              <button
                key={index}
                onClick={() => this.handleStarClick(star)}
                onMouseEnter={() => this.handleStarMousehover(star)}
                onMouseLeave={() => this.handleStarMouseout()}
              >
                <EachStar size={this.props.size} name={this.checkIsActive(star)} />
              </button>
            );
          })}
        </div>
      </>
    );
  }
}

 

 

<StarRating.scss>

.starList {
  display: flex;

  button {
    fill: grey;
  }
}

 

 

 

 

<EachStar.js>

import React, { Component } from 'react';
import './EachStar.scss';

export default class EachStar extends Component {
  render() {
    return (
      <div className="eachStar">
        <svg
          className={this.props.name}
          height={this.props.size}
          viewBox="0 -10 511.98685 511"
          width={this.props.size}
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="m510.652344 185.902344c-3.351563-10.367188-12.546875-17.730469-23.425782-18.710938l-147.773437-13.417968-58.433594-136.769532c-4.308593-10.023437-14.121093-16.511718-25.023437-16.511718s-20.714844 6.488281-25.023438 16.535156l-58.433594 136.746094-147.796874 13.417968c-10.859376 1.003906-20.03125 8.34375-23.402344 18.710938-3.371094 10.367187-.257813 21.738281 7.957031 28.90625l111.699219 97.960937-32.9375 145.089844c-2.410156 10.667969 1.730468 21.695313 10.582031 28.09375 4.757813 3.4375 10.324219 5.1875 15.9375 5.1875 4.839844 0 9.640625-1.304687 13.949219-3.882813l127.46875-76.183593 127.421875 76.183593c9.324219 5.609376 21.078125 5.097657 29.910156-1.304687 8.855469-6.417969 12.992187-17.449219 10.582031-28.09375l-32.9375-145.089844 111.699219-97.941406c8.214844-7.1875 11.351563-18.539063 7.980469-28.925781zm0 0" />
        </svg>
      </div>
    );
  }
}

 

<EachStar.scss>

.eachStar {
  .inactiveStar {
    fill: #eeeeee;
  }

  .activeStar {
    fill: #ffc107;
  }
}

 

 

 

 

 

 

'React > Today I learned' 카테고리의 다른 글

[React] useEffect hook  (0) 2021.12.14
[React] hook, props, state, event + batch  (0) 2021.12.10
fetch함수를 이용한 로그인&회원가입  (0) 2021.07.02
state,props,event  (0) 2021.07.01
Sass  (0) 2021.06.30

+ Recent posts