탭탭카드놀이) useEffect, setTimeout, clearTimeout사용하기

2022. 3. 29. 18:52프로그래밍/개인프로젝트

 

기능 개발을 하는데 setTimeout을 쓸 곳이 많았다

- 리렌더링을 위해 기존의 state값을 false로 만들고 50ms후 true로 만든다

- 카드의 이미지를 터치했을 때 보여줄 화면을 일정 시간 유지해야 한다

- 카드의 텍스트를 터치했을 때 보여줄 화면을 일정시간 유지해야 한다

- 카드리스트가 끝나고 다시 볼지 다음 단계로 넘어갈지 선택하면 레벨을 받아서 리렌더해야한다

 

시뮬레이터에서 실행은 잘 되지만 이러한 에러가 떴다

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

언마운트 된 컴포넌트에서 setState가 실행될 때 발생한다

앱에서 memory leak이 발생할 수 있으며, useEffect의 cleanup 함수를 이용해서 해결할 수 있다

 

///...

const WordPlay = () => {
//...
	const [cardSelector, setCardSelector] = useState("word1LV");
    //  cardSelector : 레벨을 지정하는 state
     
	const [mainScreenRender, setMainScreenRender] = useState(false)
    //mainScreenRender : <Main>태그를 출력해줄 토글 state
    
 	const rerenderTimeout = useRef(null); 
    useEffect(()=>{
        rerenderTimeout.current = setTimeout(() => {setMainScreenRender(true)},50)
        return() => clearTimeout(rerenderTimeout.current)
    },[mainScreenRender])
    //mainScreenRender의 값이 변경되면 50ms이 지난뒤에 다시 true로 만들고 clearTimeout함수를 실행한다
    
 	const cardCheck = (e) => {)
        setMainScreenRender(false);
        setCardSelector(e);
        setModalToggle(!modalToggle);
    }
    // setMainScreenRender를 false값으로 변경해서 화면에서 Main을 지우고,
	// 전달받은 props를 넣은 setCardSelector(e)를 통해 레벨을 변경한다
    // setModalToggle: 열린 모달창을 닫는 함수
//...

return(
//...

<LevelBtn 
    onPressOut={()=>{cardCheck("word1LV"), level1Animated(1)}}
>
    <StarViewImage source={require("../asset/images/Star1.png")} />
</LevelBtn>


//...
}

 

useEffect는 mainScreenRender가 변경될 때마다 실행이 된다

따라서 처음 렌더 됐을 때 한번 실행되므로 mainScreenRender의 기본값은 false이지만 true로 변경되고 카드 부분을 출력해준다

 

<LevelBtn>의 onPressOut에 있는 cardCheck함수는 props를 보내고 props에 따라 출력되는 카드는 변경이 된다   

동시에 mainScreenRender값을 false로 변경되는데 이때 useEffect에 의해 mainScreenRender가 true가 되면서 rerender를 진행 한 뒤에 clearTimeout함수를 실행한다

 

 

참고 : https://stackoverflow.com/questions/53090432/react-hooks-right-way-to-clear-timeouts-and-intervals