컴포넌트가 unmount 될 때 video의 src 태그를 한 번 비워줄 필요가 있었다.
기존 코드에서 video src 세팅을 ref로 분리하고, useEffect
를 통해 처리하고자 하였다.
만약 기존 코드가 아래와 같았다면,
const VideoPlayer = ({ videoUrl }: { videoUrl?: string }) => {
return <video src={videoUrl || ''} />;
}
다음과 같이 수정하였다.
const VideoPlayer = ({ videoUrl }: { videoUrl?: string }) => {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (videoRef.current && videoUrl) {
videoRef.current.src = videoUrl;
}
return () => {
if (videoRef.current) {
videoRef.current.src = '';
}
};
}, [videoUrl]);
return <video ref={videoRef} />;
}
하지만 다른 페이지로 이동하는 버튼을 클릭했을 때, 원하는 대로 동작하지 않았다. useEffect
의 cleanup 함수를 실행할 때는 이미 컴포넌트가 unmount 된 후였고, videoRef
의 접근이 불가능했다. (videoRef.current
에는 null이 들어있음)
따라서 useLayoutEffect
를 사용하여 해당 문제를 해결하였다.
다음과 같이 useEffect
를 useLayoutEffect
로 변경하였고, 다른 페이지로 이동하는 버튼을 클릭했을 때도 video의 src가 비워진 후에 페이지가 변경되는 것을 확인할 수 있었다.
const VideoPlayer = ({ videoUrl }: { videoUrl?: string }) => {
const videoRef = useRef<HTMLVideoElement>(null);
useLayoutEffect(() => {
let localRef: HTMLVideoElement | null = null;
if (videoRef.current && videoUrl) {
videoRef.current.src = videoUrl;
localRef = videoRef.current;
}
return () => {
if (localRef) {
localRef.src = '';
}
};
}, [videoUrl]);
return <video ref={videoRef} />;
}
localRef의 경우 useLayoutEffect의 cleanup 함수에서 videoRef.current의 값이 변경되었을 수도 있기 때문에 useLayoutEffect의 내부 변수에 참조를 복사하고 cleanup 함수에서 해당 변수를 사용할 수 있도록 했다. ( stackoverflow 참고 )
React Hook Flow Diagram
hook-flow에서 리액트 hook 컴포넌트의 라이프사이클을 설명하고 있는 자료를 살펴보면 다음과 같다.
이를 통해
- 렌더링
- 리액트 DOM 업데이트
useLayoutEffect
실행- 브라우저가 화면을 그림
useEffect
실행
과 같이 동작하기 때문에 컴포넌트가 unmount 되기 전 useEffect
의 cleanup 함수에서 video의 src를 비워주고자 했던 동작은 실행되지 않는다는 것을 알 수 있다.
'정리용' 카테고리의 다른 글
React Query의 InvalidateQueries가 동작하지 않을 때 (1) | 2022.09.14 |
---|---|
[React] 일정시간동안 이벤트 발생이 없으면 콜백 함수 실행 (0) | 2022.08.09 |
크롬에서 막혀있는 포트 (0) | 2022.07.01 |
Proxy 서버로 CORS 해결하기 (0) | 2022.06.24 |
Docker 명령어 정리 (0) | 2022.05.25 |