🪁react/react 실습

lotto앱과 setTimeout | celarTimeout | Array.from[자신감up 실습15]

하얀성 2024. 2. 2. 09:37

렌더링 과정 :

count라는 state 변수가 random으로 돌아가게 하면서 numbers state 배열을 통해서 값 중복을 방지.

useEffect를 통해서 배열을 바꿔주는 addNumber 함수와 count에 랜덤 중에서 한 개의 값을 부여하는 . 그 두가지 상황 때만 setTimeout이 멈추게 하여 여러 값중에서 한개의 값을 랜덤으로 count에 지정. 이 useEffect를 관리하는 두 함수는 버튼의 click 속성을 통해서 관리

 

랜더링과정 요약 내용 피드백 후, 추가 내용

Array.from을 사용하여 5개의 Lotto 컴포넌트를 생성합니다. 각 컴포넌트에는 numbers 배열과 addNumber 함수가 props로 전달됩니다.

clearTimeoutuseEffect의 정리 단계에서 실행되어, 컴포넌트가 언마운트되거나 의존성이 변경될 때 타이머를 정리합니다.


렌더링된 모습



Q1. setTimeout 형식 차이가 어떤 영향을 주는가?

setTimeout(() => {generateRandomNumber
     
    }, 500);
  };

 

setTimeout(generateRandomNumber, 500);
 

 

둘의 역할은 동일. 똑같이 500밀리초 이후에 함수를 실행.

하지만 화살표함수가 추가적인 로직이나 매개변수를 적용할 수 있는 유연성을 제공함.

 


Q2. 왜 위는 되고 아래는 안되는 거지??

function Lotto() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const generateRandomNumber = () => {
      let randomNumber = Math.random();
      setTimeout(generateRandomNumber, 500);

      setCount(randomNumber);
    };
    generateRandomNumber(); // 차이나는 부분
  }, []);
 

function Lotto() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const generateRandomNumber = () => {
      let randomNumber = Math.random();
      setTimeout(generateRandomNumber, 500);

      setCount(randomNumber);
    };

  }, []);

    generateRandomNumber();  // 차이나는 부분

 

두 번째 코드:

generateRandomNumber 함수는 useEffect의 외부에서 호출됩니다.
그러나 이 함수는 useEffect 내부에서 정의되기 때문에, useEffect 외부의 범위에서는 이 함수에 접근할 수 없습니다.
즉, generateRandomNumber 함수는 useEffect 외부에서 호출될 때 "정의되지 않은 함수"라는 오류를 발생시킵니다.


JavaScript에서는 함수가 정의된 범위(scope) 내에서만 접근이 가능하므로, 이 경우 useEffect 내부에서 정의된 generateRandomNumber는 해당 범위를 벗어난 곳에서는 호출할 수 없습니다.

 


Q3. if문 만으로 번호 랜덤 생성이 멈춰야 할 것 같은데 멈추지 않는 이유는?

 

ㅡ> 앞으로 generate가 실행되는건 if문을 통해 막아주는데, 그 이전 ture된 값은 계속 무한 루프로 돌아가니까

 clearTimeout으로 아예 setTimeout을 제거해야함.

function Lotto() {
  const [count, setCount] = useState(0);
  const [isRunning, setIsRunning] = useState(true);
  useEffect(() => {
    let idTimer;
    const generateRandomNumber = () => {
      let randomNumber = Math.floor(Math.random() * 4.9 + 1);
      idTimer = setTimeout(generateRandomNumber, 500);
      setCount(randomNumber);
    };
    if (isRunning) generateRandomNumber();

    return () => {
      clearTimeout(idTimer);
    };
  }, [isRunning]);

  const stop = () => {
    setIsRunning(!isRunning);
  };

 

상황 분석
isRunning이 true일 때: generateRandomNumber 함수는 500밀리초마다 자신을 재귀적으로 호출하여 타이머를 설정합니다.


isRunning이 false로 변경될 때:
if문은 더 이상 generateRandomNumber 함수를 호출하지 않습니다. 즉, 새로운 타이머 설정을 막습니다.
그러나 이미 활성화된 타이머(이미 예약된 호출)는 if문만으로는 중지되지 않습니다.


clearTimeout의 역할:
clearTimeout을 사용하면, 이미 설정된 타이머를 취소할 수 있습니다. 즉, 이미 예약된 generateRandomNumber 호출을 중지합니다.
이는 useEffect의 정리 단계에서 구현되며, 컴포넌트의 상태가 변경되거나 컴포넌트가 언마운트될 때 실행됩니다.

 


Array.from({ length: 5 }, callback);

callback 구성: 

 

(element, index) => {
  // 여기서 element는 현재 요소의 값, index는 해당 요소의 인덱스입니다.
}

  • Array.from은 배열을 생성하고 초기화하는 데 사용됩니다. 여기서는 특정 길이의 배열을 생성하고 각 요소에 대해 React 컴포넌트를 반환합니다.
  • 콜백 함수에서 element 인자를 사용하지 않더라도, index 인자를 올바르게 두 번째 위치에 두어야 합니다.

-올바른 사용예시-

{Array.from({ length: 5 }, (element, index) => (
        <Lotto key={index} numbers={numbers} addNumber={addNumber} />
      ))}

 

Array.from의 인자는 실제로 배열의 현재 요소(element)이고, 두 번째 인자가 index입니다. 따라서 index를 첫 번째 인자로 사용한다면 이는 잘못된 접근입니다.