• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

6-4강 useEffect 배열 입력값에 따른 로또 중복공 발생 질문

21.11.14 20:55 작성 조회수 129

0

안녕하세요 제로초님 항상 좋은 강의 감사드립니다 :)

유튜브로 강의를 수강하다가, 인프런/유튜브 댓글에 같은 질문이 없어 질문을 남깁니다. (사실 하나 있긴 했는데 이해가 잘 안되더군요 ㅜㅜ)

강의에서 아래와 같이 useEffect의 배열에 winBalls.length===0을 넣으면 첫번째 공과 두번째 공이 중복으로 나오고, timeouts.current로 넣으면 의도한대로 제대로 공이 중복되지 않게 나오는 것을 확인할 수 있었습니다.

 

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

class형에서는 winBalls.length===0으로 해도 문제없지만 hooks에서는 문제가 발생한 이유를 저는 componentDidMount와 componentDidUpdate 역할을 useEffect가 한번에 해주기 때문에 중복발생하는 것으로 이해했습니다.

(useEffect에서 winBalls.length===0이라는 조건문에 mount,update할 때 각각 부합해서 중복발생하는 것으로 이해하였습니다.)

 

1. 그런데, timeouts.current을 배열에 넣을 때는 처음 mount될 때나 update될 때나 똑같이 빈 배열일텐데 왜 같은 공이 중복발생하지 않고 의도대로 제대로 작동하는지 궁금합니다.

 

2. winBalls.length===0과 같이 조건문을 useEffect 배열에 넣어도 되는건가요? 만약 가능하다면, winBalls.length===0을 배열에 넣을 경우, 위 중복 공 발생버그를 해결할 수 있는 방안도 있을까요?

 

항상 감사드립니다!

 

 

답변 1

답변을 작성해보세요.

0

winBalls.length === 0이나 timeouts.current 둘 다 넣으실 필요가 없습니다.

제가 설명 잘못 한 부분 중 하나인데 ref인 timeouts는 []에 넣어도 아무 영향이 없습니다. 그냥 deps를 []로 하시면 됩니다.

답변 감사합니다. 그런데 아직 헷갈리는 점이 있습니다. deps를 빈 배열로 해주면, 결국 class형 컴포넌트에서의 componentDidMount만 해주는 것과 같으므로 componentDidUpdate가 일어나지 않아 한판더 기능이 불가능할 것 같은데 혹시 추가설명을 부탁드려도 될까요?

아, 오랜만에 소스코드를 다시 보는 것이라 이제 이해했습니다.

deps에 timeout.current 넣으셔야 합니다. 일반적으로는 deps에 ref를 넣는게 의미 없지만 여기서는 좀 역할을 합니다.

한 판 더에서는 onClickRedo를 실행합니다. 여기서 timeout.current = []; 부분에서 새 배열을 할당하고 참조가 바뀌게 되어서 useEffect를 다시 실행하게 됩니다.

감사합니다. 혹시 deps를 winBalls.length===0으로 할 때엔 맨처음에 위 사진처럼 중복 공이 두번 발생하는 이유가, componentDidMount에서 한 번, 그리고 공이 생기면서 false로 바껴 componentDidUpdate가 발생해서 componentDidMount가 진행을 멈추고 update가 발생해서 맨처음 중복공만 두 번 발생하는게 맞나요?

네 처음 1초가 지난 뒤 첫 공을 그리고 deps 값이 false가 되어 기존 타이머가 취소되고 다시 나머지 공을 그리는 타이머가 돌아가는 것 같습니다.

감사합니다 :)