[2022.08.17] 리액트로 로또 추첨기 만들기 (클래스 컴포넌트)

REASON·2022년 8월 17일
0

React

목록 보기
22/27

제로초님 영상 보고 따라 만들어본 리액트 로또 추첨기 컴포넌트!

리액트보다 자바스크립트 문법이 더 어렵게 느껴졌다. ㅠㅠ
특히 getWinNumbers 함수 안에 작성된 코드를 좀 더 살펴보고 혼자 만들어보는 시간을 가져봐야겠다!

/* Lotto.js */
import React, { Component } from 'react';
import Ball from './Ball';

function getWinNumbers() {
  console.log('getWinNumbers');
  const candiate = Array(45)
    .fill()
    .map((v, i) => i + 1);
  const shuffle = [];

  while (candiate.length > 0) {
    shuffle.push(candiate.splice(Math.floor(Math.random() * candiate.length), 1)[0]);
  }

  const bonusNumber = shuffle[shuffle.length - 1];
  const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
  return [...winNumbers, bonusNumber];
}

class Lotto extends Component {
  state = {
    winNumbers: getWinNumbers(),
    winBalls: [],
    bonus: null,
    redo: false,
  };

  timeouts = [];

  onClickRedo = () => {
    this.setState({
      winNumbers: getWinNumbers(),
      winBalls: [],
      bonus: null,
      redo: false,
    });
    this.timeouts = [];
  };

  runTimeouts = () => {
    const { winNumbers } = this.state;

    for (let i = 0; i < winNumbers.length - 1; i++) {
      this.timeouts[i] = setTimeout(() => {
        this.setState((prevState) => {
          return { winBalls: [...prevState.winBalls, winNumbers[i]] };
        });
      }, (i + 1) * 1000);
    }
    this.timeouts[6] = setTimeout(() => {
      this.setState({
        bonus: winNumbers[6],
        redo: true,
      });
    }, 7000);
  };

  componentDidMount() {
    this.runTimeouts();
  }

  componentDidUpdate(prevProps, prevState) {
    if (this.state.winBalls.length === 0) {
      this.runTimeouts();
    }
  }

  componentWillUnmount() {
    this.timeouts.forEach((t) => {
      clearTimeout(t);
    });
  }

  render() {
    const { winBalls, bonus, redo } = this.state;
    return (
      <>
        <div>당첨 숫자</div>
        <div id="result">
          {winBalls.map((v) => (
            <Ball key={v} number={v} />
          ))}
        </div>
        <div>보너스!</div>
        {bonus && <Ball number={bonus} />}
        {redo && <button onClick={this.onClickRedo}>한번 더!</button>}
      </>
    );
  }
}

export default Lotto;
/* Ball.jsx */

import React, { memo } from 'react';

const Ball = memo(({ number }) => {
  let background, color;

  if (number <= 10) {
    background = 'red';
  } else if (number <= 20) {
    background = 'orange';
  } else if (number <= 30) {
    background = 'yellow';
  } else if (number <= 40) {
    background = 'blue';
    color = 'white';
  } else {
    background = 'green';
  }

  return (
    <div className="ball" style={{ background, color }}>
      {number}
    </div>
  );
});


export default Ball;

1초마다 랜덤으로 뽑은 숫자볼 한개씩 보여주도록 하는 간단한 웹 게임이다.
마지막 보너스 숫자볼을 보여줄 때 '한번 더' 버튼이 나타나서 다시 숫자볼을 뽑아볼 수도 있다.

다시 살펴볼 코드

function getWinNumbers() {
  console.log('getWinNumbers');
  const candiate = Array(45)
    .fill()
    .map((v, i) => i + 1);
  const shuffle = [];

  while (candiate.length > 0) {
    shuffle.push(candiate.splice(Math.floor(Math.random() * candiate.length), 1)[0]);
  }

  const bonusNumber = shuffle[shuffle.length - 1];
  const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
  return [...winNumbers, bonusNumber];
}

여러 배열 내장 함수를 혼용해서 사용하는 체이닝 방식으로 작성되어서 어려웠기 때문에 이 부분을 중점적으로 보고 다시 만들어봐야겠다.


참고 자료
로또 추첨기 컴포넌트

0개의 댓글