이번 시간에 중요한 주제를 다루겠습니다
이 부분의 코드는 결국
부수 효과로서 JSX 코드를 산출하는 것에
직접적으로 연관되지 않았습니다
그리고 useEffect로 말씀드린 타이머 문제를 해결할 수 있습니다
지난 강의에서 보여드렸듯이 useEffect를 가지고
이 타이머를 이 컴포넌트가 사라질 때
멈출 수 있습니다
그 작업을 보여드리겠습니다
리액트에서 useEffect를 불러오겠습니다
그리고 타이머를 설정하겠습니다
useEffect를 사용해서 Effect 함수와 의존성 배열을
여기에 넣겠습니다
그러면 이제 해당 코드를
Effect 함수 안으로 옮길 수 있습니다
그리고 이 타이머를 설정할 때는
이 Effect 기능이 필요하지 않습니다
타이머를 설정하는 작업에 문제가 있는 게 아니기 때문입니다
이전의 이용자 장소 작업과 비슷하게
무한 루프를 만들어내지 않을 뿐더러
아직 연결이 되지 않았던 ref (참조)를
해결할 필요가 있던 모달에서
겪었던 문제도 없기 때문입니다
여기서의 문제는 타이머를 설정하는 것이 아니라
이 컴포넌트 함수가 사라질 때
cleanup (클린업) 함수로 타이머의 내용을 삭제하는 것입니다
useEffect는 이 부분의 작업에도 도움을 줍니다
useEffect를 사용할 때, 이 Effect 함수뿐만 아니라
이 Effect 함수가 다시 작동하기 바로 전에
실행해야 하는 클린업 함수도
정의되지 않았었습니다
이러한 클린업 함수를 Effect 함수 안에
돌려놓음으로써 정의할 수 있습니다
그래서 이 Effect 함수는 다른 함수를 반환할 수 있는데
해당 함수는 리액트에 의해 실행되는데
그 시점이 이 effect 함수가 다시 작동하기 바로 전이나
여기 이 상황처럼
이 컴포넌트가 사라지기 바로 전에 실행됩니다
즉 DOM에서 삭제되기 전 실행됩니다
그러므로 이제 클린업 함수에서
타이머를 멈출 수 있습니다
그러기 위해서 브라우저의
내장된 clearTimeout 함수를 사용할 수 있습니다
이제 필요한 것은 멈출 타이머에 대한
reference (참조) 입니다
참조는 setTimeout에 의해 반환되므로
간단하게 상수 안에 setTimeout을 넣을 수 있고
timer라고 이름 지은 타이머를 clearTimeout으로 전달하면
이 컴포넌트가 DOM에서 삭제될 때마다
타이머를 멈추게 됩니다
여기에서 중요한 부분이 하나 있습니다
이 클린업 함수는
Effect 함수가 다시 작동할 때 실행되고
클린업 함수는 그 직전인
Effect 함수가 작동하기 바로 전에 실행됩니다
하지만 여기에서는 불가능합니다
의존성을 만들지 않았기 때문에
Effect 함수가 다시 작동하지 않습니다
보시다시피 여기에 경고 표시가 있습니다
그래서 의존성을 추가해야 하지만
즉 여기 사용되고 있는 onConfirm 속성을
의존성으로 추가해야 합니다
저는 의도적으로 이 작업을 아직 하지 않았습니다
이유는 조금 있다가 설명드리겠습니다
일단 코드를 이 상태로 둬 보겠습니다
그러면 클린업 함수는 딱 한 번만 작동할 것입니다
컴포넌트가 삭제될 때입니다
일단 저장하고 새로고침을 해서
이제 정렬된 장소들이 뜰 때까지 기다려 보면
당연하게도 장소를 추가할 수 있고
장소를 열고 취소를 클릭하면
타이머가 설정되는 것을 볼 수 있으며, 이전에 있던
타이머가 멈추지 않고 만료되어
장소가 혼자 사라지는 그 문제가 해결됐습니다
이 문제가 더 이상 발생하지 않는 이유는
함수가 그 타이머 내용을 삭제하고 있기 때문이고
'타이머 내용 삭제 중'이라는 console.log를 추가해
타이머의 설정 및 내용 삭제를 실시간으로 확인할 수 있습니다
새로고침 후 클릭하고 취소를 누르면
아까 만든 문구가 보입니다
중요한 점은 이 클린업 함수가
Effect 함수가 최초로 작동되기 바로 전에
작동하지 않는다는 것입니다
이 함수는 Effect 함수의 최초 실행 다음부터
차후 실행 바로 전에만 작동합니다
그리고 언급된 것처럼 이 컴포넌트가 삭제될 때에만 실행됩니다
그렇게 해서 이제 앱 내에서 버그가 발생하지 않도록
타이머를 관리할 수 있게 되었습니다