이제 이 의존성 배열을 떠나서
useEffect에는 여러분이 유념해야 할 다른 기능이 하나 있습니다
해당 기능을 다루기 위해
여기의 DeleteConfirmation 컴포넌트 파일로 가봅시다
해당 컴포넌트는 이 모달 내용의
렌더링을 담당합니다
이제 해당 앱에 기능 하나를 추가하겠습니다
이 기능은 3초 뒤에 해당 모달이 자동으로 꺼지게 할 것이고
방문지를 자동으로 삭제할 것입니다
그래서 해당 모달이 자동으로
3초 뒤에 수락되는 것입니다
그래서 해당 기능을 적용하기 위해, 타이머를 설정해야 합니다
이는 또 다른 브라우저 기능의 도움을 받아서 설정할 수 있습니다
바로 이 setTimeout 함수입니다
브라우저 자체에 내장된 함수이며
SetTimeout 기능은 두 개의 인수를 필요로 합니다
첫 번째 인수는 함수입니다
두 번째 인수는 밀리초로 계산된 시간입니다
예를 들어, 3,000밀리초는 3초입니다
그리고 첫 번째 인수로 전달한 해당 함수는
정한 기간이 종료되면 실행될 것입니다
그래서 3초 후에 이 모달을 끄려면
3초 뒤에 실행되는 onConfirm을
callback (콜백) 함수 안에 넣어둬야 합니다
그래서 이 컴포넌트가 렌더링됐을 때
이 타이머가 설정되고
3초 후에 onConfrim이 실행될 것입니다
그런데 지금 이 코드에는 몇 가지 문제점이 있습니다
그 중 한 가지는 이 DeleteConfirmation 컴포넌트가
항상 렌더링 된다는 것입니다
여기의 앱 컴포넌트에 의해 렌더링 되는 이 함수는
Modal 컴포넌트가 감싸고 있으며
이 또한 항상 렌더링됩니다
그저 DOM에서 항상 안 보이는 것뿐인데
Modal 컴포넌트는 내부적으로 보이게 하거나 숨겨서
여기 open 속성을 통해 모달 창이 보이도록 조정하기 때문입니다
하지만 기술적인 측면에서 이 DeleteConfirmation 컴포넌트는
언제나 DOM의 한 부분이며
그렇기 때문에 앱 컴포넌트가 최초로 렌더링 될 때
해당 타이머도 설정되고 시작됩니다
왜냐하면 해당 렌더링 작업동안
이또한 렌더링되기 때문입니다
이 문제를 우회하기 위해선
DeleteConfirmation을
modalIsOpen 조건부로 렌더링 하면 됩니다
그렇게 하면 모달이 열린 상태가 True일 때에만 렌더링됩니다
이렇게 하면 해당 문제를 우회하여 문제를 해결할 수 있습니다
그리고 또한 타이머가 항상 시작 부분에
설정되지 않도록 해주겠습니다
더 명쾌한 해결책은 이 곳에서 렌더링하는 것입니다
그런데 그러려면 Modal 컴포넌트에 가서
이 자식 속성을 생성하지 않음으로써
앱 컴포넌트가
조건적으로 이를 렌더링 하지 않도록 해야 합니다
대신에, Modal 컴포넌트가 렌더링되면
더 명확해지고
이제 우리가 open이 True인지 확인할 수 있고
그러한 경우라면 자식 속성을 생성하게 되고
그렇지 않다면 null (널) 값을 렌더링 합니다
이게 또 다른 해결책이 될 수 있겠습니다
이 또한 타이머가
바로 설정되지 않도록 합니다
그리고 이제 타이머 설정을
consol.log를 통해 설정할 수 있습니다
이대로 저장하고 새로고침을 하면
로그에서 해당 내용이 보이지 않기 때문에
타이머가 바로 설정되지 않는다는 것을 알 수 있습니다
그런데 이 코드에는 아직 문제가 있습니다
이 문제점이 무엇인지 보여드리겠습니다
여기에 있는 항목 중 하나를 삭제해 보겠습니다
그러면 타이머가 설정되는 것을 볼 수 있습니다
그리고 3초 후에 항목이 삭제됩니다
그러나 3초가 지나기 전에 직접 삭제한다면
타이머를 멈추지 않았으므로 만료됩니다
이것 자체로 문제가 발생하지는 않았지만
취소를 클릭하게 된다면 문제가 발생할 것입니다
보시다시피 취소를 클릭하게 되더라도
3초 후에 항목이 사라지게 됩니다
이는 타이머가 멈추지 않았기 때문입니다
이 컴포넌트가 더 이상 렌더링되지 않으면, 즉
취소를 눌렀든 수락을 눌렀든
해당 컴포넌트가 현재 보이든 안 보이든
여전히 타이머가 시작이 되고 지속이 된다면
이것은 문제가 됩니다
다행히 이는 useEffect로 해결할 수 있습니다