리액트 로또 추첨기 만들기

hhkim·2021년 7월 28일
0
post-thumbnail

🔗 react-lotto 완성본

웹 게임을 만들며 배우는 React에서 실습했던 내용을 토대로 다시 만들어보는 로또 추첨기


프로젝트 세팅

  • create-react-app 프로젝트 생성
    npx create-react-app react-lotto

코드 작성

  • 막상 하고 보니까 강의랑 다른 점이 딱히 없네...
  • useCallback()은 필요성을 못 느껴서 쓰지 않았다.
    👉 다음 강의 보니까 이벤트 처리 함수에는 기본적으로 써주는 게 좋다는 듯?

    memo()

    공식 문서
    컴포넌트의 렌더링 결과를 메모이징하여, props가 변경되지 않는 이상 리렌더링하지 않는다.

Lotto.js

import React, { useState, useRef, useEffect, useMemo } from 'react';
import Ball from './Ball';

function getWinNumbers() {
  const balls = Array(45)
    .fill()
    .map((v, i) => i + 1);
  const shuffle = [];
  while (balls.length > 0) {
    shuffle.push(balls.splice(Math.floor(Math.random() * balls.length), 1)[0]);
  }
  const bonus = shuffle[shuffle.length - 1];
  const winBalls = shuffle.slice(0, 6).sort((a, b) => a - b);

  return [...winBalls, bonus];
}

const Lotto = () => {
  const lottoNumbers = useMemo(() => getWinNumbers(), []);
  const [winNumbers, setWinNumbers] = useState(lottoNumbers);
  const [winBalls, setWinBalls] = useState([]);
  const [bonus, setBonus] = useState(null);
  const [redo, setRedo] = useState(false);
  const timeouts = useRef([]);

  useEffect(() => {
    for (let i = 0; i < winNumbers.length - 1; i++) {
      timeouts.current[i] = setTimeout(() => {
        setWinBalls((prevWinBalls) => [...prevWinBalls, winNumbers[i]]);
      }, (i + 1) * 1000);
    }
    timeouts.current[6] = setTimeout(() => {
      setBonus(winNumbers[6]);
      setRedo(true);
    }, 7000);
    return () => {
      timeouts.current.forEach((v) => {
        clearTimeout(v);
      });
    };
  }, [winNumbers]);

  const onClickRedo = () => {
    setWinNumbers(getWinNumbers());
    setWinBalls([]);
    setBonus(null);
    setRedo(false);
    timeouts.current = [];
  };

  return (
    <>
      <div>당첨 숫자</div>
      {winBalls.map((v) => (
        <Ball key={v} number={v} />
      ))}
      <div>보너스</div>
      {bonus && <Ball key={bonus} number={bonus} />}
      {redo && <button onClick={onClickRedo}>다시!</button>}
    </>
  );
};

export default Lotto;

Ball.js

import React, { memo } from 'react';
import './Ball.css';

const Ball = memo(({ number }) => {
  let background;
  if (number < 10) {
    background = 'red';
  } else if (number < 20) {
    background = 'orange';
  } else if (number < 30) {
    background = 'yellow';
  } else if (number < 40) {
    background = 'blue';
  } else {
    background = 'green';
  }
  return (
    <div className="ball" style={{ backgroundColor: background }}>
      {number}
    </div>
  );
});

export default Ball;

0개의 댓글