inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

웹 게임을 만들며 배우는 React

6-6. Hooks에 대한 자잘한 팁들

로또 질문있습니다.

246

Jack

작성한 질문수 11

0

안녕하세요 제로초님!


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);
  console.log("winNumbers1:", winNumbers);

  return [...winNumbers, bonusNumber];
}

const Memo = () => {
  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([]);

  console.log("winNumbers2:", winNumbers);
  console.log("winBalls:", winBalls);

  useEffect(() => {
    console.log("useEffect");
    for (let i = 0; i < winNumbers.length - 1; i++) {
      timeouts.current[i] = setTimeout(() => {
        setWinBalls((prevBalls) => [...prevBalls, winNumbers[i]]);
      }, (i + 1) * 1000);
    }
    timeouts.current[6] = setTimeout(() => {
      setBonus(winNumbers[6]);
      setRedo(true);
    }, 7000);
    return () => {
      timeouts.current.forEach((v) => {
        clearTimeout(v);
      });
    };
  }, [timeouts.current]); // 빈 배열이면 componentDidMount와 동일
  // 배열에 요소가 있으면 componentDidMount랑 componentDidUpdate 둘 다 수행

  useEffect(() => {
    console.log("로또 숫자를 생성합니다.");
  }, [winNumbers]);

  const onClickRedo = useCallback(() => {
    console.log("onClickRedo");
    console.log(winNumbers);
    setWinNumbers(getWinNumbers());
    setWinBalls([]);
    setBonus(null);
    setRedo(false);
    timeouts.current = [];
  }, [winNumbers]);

강좌와 같은 코드에서 getwinNumbers 함수안에서 winNumbers의 값을(winNumbers1) 콘솔로 한번 찍고

 
function getWinNumbers() {
......
  console.log("winNumbers1:", winNumbers);

  return [...winNumbers, bonusNumber];
}

이번에는 Memo 안에서 winNumbers를 (winNumbers2)콘솔로 찍어보고

const Memo = () => {
  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([]);

  console.log("winNumbers2:", winNumbers);
  console.log("winBalls:", winBalls);

브라우저를 실행하면

이와같이 winNumbebrs1과 2가가 처음에는 두개의 콘솔 모두 같은 값이었다가 useEffect가 실행되고 나서 값이 바뀝니다.

이런 현상은 초기 렌더링이거나 새로고침을 하면 똑같이 일어납니다.

하지만 onClickRedo한번더를 누르면 그제서야 winNumbers의 값이 같게 나옵니다. 

왜 처음렌더링하거나 새로고침시 값이 다르게 나오는지 궁급하니다!.

 

2.  

강의 5-2 에서

 

componenetDidMount () {

const {imageCord} = this.state

this.interval = setInterval( () => {

console.log("hello", this state.imageCord, rspCoords,가위)

if (imageCord === repCoords.바위)

.......

}

}

이코드에서 비동기 함수 바깥에 있는 변수 imgeCord를 참조해서 클로져 에러가 발생한다고 하셨잖아요?

const Memo = () => {
  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(() => {
    console.log("useEffect");
    for (let i = 0; i < winNumbers.length - 1; i++) {
      timeouts.current[i] = setTimeout(() => {
        setWinBalls((prevBalls) => [...prevBalls, winNumbers[i]]);
      }, (i + 1) * 1000);
  }

그런데 이코드에서 setTimeout 비동기 함수에서 winNumbers와 timeouts도 useState에 있는 변수?(상수)인데 이때는 왜 클로져 문제가 발생하지 않는지 궁금합니다!

 

 

 

react

답변 1

0

제로초(조현영)

1.저는 이 문제가 발생하지 않는데 저와 코드가 다른 것 같습니다.

2. let i와 setTimeout의 콜백함수 간에 클로저 관계가 생성되어서 해결되었기 때문입니다. 즉, 이 방법이 클로저 문제의 모범답안입니다.

npm run dev 실행 시 포트가 안뜨는 문제

0

240

2

timeouts.current를 useEffect 의 input값으로 넣었을때

0

98

2

렌더링 테스트 코드 (Hooks)

0

93

1

Cannot find package 'react-refesh' 이런 에러 뜨시는 분들 보세요.

0

167

1

해당 에러 뜨는 분들 보세요. "Uncaught TypeError: ReactDom.createRoot is not a function"

1

209

1

강사님 레포지토리에서 코드 복사 시 master 브랜치 말고 react18 브랜치꺼 복붙하세요ㅠㅠ

0

108

1

useMemo와 useCallback 사용 시기

0

222

2

onRightClickTd가 작동을 하지 않습니다.

0

237

1

action.type 불러오는 방식

0

226

2

onClickRedo 질문

0

177

1

const Try = require(./Try) 빨간줄

0

262

1

npx webpack 실행시

0

324

1

지뢰찾기 강좌에서 빈칸들 한번에 열기 파트에서 여쭤보고싶은부분이 있어서 글 올립니다.

0

243

1

강좌에서 다루지 않은 기능들은 어떻게 학습하면 좋을까요?

0

319

1

react devtool이 enable 않됩니다.

0

548

2

React 랜더링이 되지 않습니다.

0

422

2

비동기로 동작하는 setState에 대해서

0

340

1

npm run dev 할 때 에러발생

0

497

2

memo, PureComponenet, shouldComponentUpdate 관련 질문

0

211

1

devMiddleware의 필요성

0

359

1

리액트에서 화살표 함수를 사용해야하는 이유

0

948

2

path.join관련질문

0

288

2

2-9. 웹팩 데브 서버와 핫 리로딩 설치과정 시 에러

0

384

1

next.js 에서 이와 비슷한 예제를 돌리고있는데 react랑 달라서 질문 드립니

1

503

4