가위바위보에서 굳이 useEffect나 componentDidMount 에서만 setInterval을 사용하는건 아니고, 필요할 때 setInterval을 쓰고 componentWillUnMount에서 정리만 잘하면 된다.

 

Hooks는 함수 컴포넌트를 말하는 것이 아니라 useEffect, useState 같은 것들을 말하는 것이다.

 

Lotto.jsx (내가 만든 코드 + 강의코드)

import React, {Component} from "react";
import Ball from "./Ball";

const winBall = () => {
    const balls = Array(45).fill(0).map((v,i) => i+1);
    const result = [];
    while(balls.length > 0){
        const randIndex = Math.floor(Math.random() * balls.length); // <= 0 x < length
        result.push(balls.splice(randIndex, 1)[0]);
    }
    const bonus = result[result.length - 1]; //맨 마지막
    const wins = result.slice(0,6).sort((a,b)=>a-b); // 0~5
    console.log(wins, bonus);
    return [...wins, bonus];
}

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

    componentDidMount() {
        console.log('componentDidMount')
        this.startLotto();
    }

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

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

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

    startLotto = () => {
        const length = this.state.winNumbers.length - 1;
        for(let i=0; i<length; i++){
            const timerId = setTimeout(()=>{
                this.setState((prev)=>{
                    const winBall = prev.winNumbers.slice(i,i+1)[0];

                    return {
                        winNumbers:[...prev.winNumbers],
                        winBalls:[...prev.winBalls, winBall],
                        bonus:null,
                        redo:false
                    }
                });
            },1000 * (i+1));
            this.timeouts.push(timerId);
        }

        this.timeouts[6] = setTimeout(()=>{
            this.setState({bonus: this.state.winNumbers[length],redo:true});
        }, 1000 * this.state.winNumbers.length);
    }

    render() {
        const {winNumbers, winBalls, bonus, redo} = this.state;
        return (
            <>
                {winBalls.map(v=><Ball number={v} key={v+1}/>)}

                {
                    bonus && <><div className="bonus__comment">보너스!</div><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 = null;
    if(number >= 40){
        background = 'red';
    }else if(number >= 30){
        background = 'green';
    }else if(number >= 20){
        background = 'yellow';
    }else if(number >= 10){
        background = 'blue';
        color = 'white';
    }else{
        background = 'aqua';
    }

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

export default Ball;

 

 

LottoHooks.jsx

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

const LottoHooks = () => {
    const winBall = () => {
        const balls = Array(45).fill(0).map((v,i) => i+1);
        const result = [];
        while(balls.length > 0){
            const randIndex = Math.floor(Math.random() * balls.length); // <= 0 x < length
            result.push(balls.splice(randIndex, 1)[0]);
        }
        const bonus = result[result.length - 1]; //맨 마지막
        const wins = result.slice(0,6).sort((a,b)=>a-b); // 0~5
        console.log(wins, bonus);
        return [...wins, bonus];
    }

    const [winNumbers, setWinNumbers] = useState(winBall);
    const [winBalls, setWinBalls] = useState([]);
    const [bonus, setBonus] = useState(null);
    const [redo,setRedo] = useState(false);
    const timerRef = useRef([]);


    useEffect(()=>{
        for(let i=0; i<6; i++){
            const timerId = setTimeout(()=>{
                setWinBalls((prev)=>{
                    return [...prev, winNumbers[i]];
                });
            },(i+1) * 1000);
            timerRef.current.push(timerId);
        }
        timerRef.current[6] = setTimeout(()=>{
            setBonus(winNumbers[6]);
            setRedo(true);
        },7000);
    },[winNumbers]);

    const onClickRedo = (param) => (e) => {
        console.log(param);
        console.log(e.target);
        setWinBalls([]);
        setWinNumbers(winBall);
        setBonus(null);
        setRedo(false);
        timerRef.current = [];
    }

    return (
        <>
            {
                winBalls.map((v,i) => <Ball number={v} key={v+i}/>)
            }
            {
                bonus && <><div>보너스!!</div><Ball number={bonus} /></>
            }
            {
                redo && <button onClick={onClickRedo(1)}>한번더</button>
            }
        </>
    );
}

export default LottoHooks;

+ Recent posts