인프런 커뮤니티 질문&답변

o6o4_님의 프로필 이미지

작성한 질문수

웹 게임을 만들며 배우는 React

6-4. useEffect로 업데이트 감지하기

getWinNumbers가 여러번 실행되지 않는데 업데이트된건가요?

21.12.09 14:55 작성

·

194

0

콘솔로 getWinNumbers를 찍어보았는데 componentDidMount때 딱 한 번 실행되고 재실행되지 않는 것 같습니다. 제가 코드를 강의와 똑같이 작성한다고 한건데, 혹시 잘못 작성해서 의도와 다르게 작성된 부분이 있어서 그런 것인지 아니면 버전이 업데이트된 것인지 궁금해서 질문 남깁니다!

const React = require('react');
const { useState, useRef, useEffect } = React;
const Ball = require('./Ball');

function getWinNumbers() {
    console.log('getWinNumbers');
    const candidate = Array(45).fill().map((v, i) => i + 1);
    const shuffle = [];
    while (candidate.length > 0) {
        shuffle.push(candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0]);
    }
    const bonusNumber = shuffle[shuffle.length - 1];
    const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
    return [...winNumbers, bonusNumber];
}

const LottoHooks = () => {

    const [winNumbers, setWinNumbers] = useState(getWinNumbers);
    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 () => { // componentWillUnmount
            timeouts.current.forEach((v) => {
                clearTimeout(v);
            });
        };
    }, [timeouts.current]);

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

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

}

module.exports = LottoHooks;

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

2021. 12. 09. 17:25

useState(getWinNumbers)

이렇게 하면 한 번만 실행됩니다.

제 코드는 useState(getWinNumbers()); 였습니다.

강좌에서는 useMemo로 해결했지만 또 다른 해결 방법이 useState(getWinNumbers); 입니다.

o6o4_님의 프로필 이미지
o6o4_
질문자

2021. 12. 09. 17:46

아 그렇군요! 타이핑 실수인건데 어떻게 얻어걸렸네요.. 함수인데 뒤에 괄호를 붙이지 않아도 실행이 되는 건가요? 

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

2021. 12. 09. 22:19

useState가 알아서 실행시킵니다~

o6o4_님의 프로필 이미지

작성한 질문수

질문하기