Posts
웹 복귀, 이탈 이벤트 감지하기
웹 복귀, 이탈 이벤트 감지하기
visibilityChange로 웹 페이지의 복귀, 이탈 이벤트를 다뤄보자.
Overview
사용자가 웹 페이지를 떠날 때 react-query의 refetch를 중단하거나, 다른 탭에서 다시 복귀했을 경우 클라이언트 데이터를 최신화 해주어야할 상황이 있다.
이러한 기능이 필요할 때 사용 할 수 있는 visibilityState
와 visibilitychange
를 알아보자.
웹 페이지에서 사용자에게 실제로 페이지를 떠날 것인지 묻는 확인 대화 상자 표시는
beforeunload
이벤트를 사용한다.
웹 페이지에서 visibility 다루기
Document 객체에 내장된 Document.visibilityState
는 다음과 같이 document의 가시성 1 상태를 반환한다.
visible
: 페이지가 최소화 되지 않은 창(브라우저)에서의 선택된 탭.hidden
: document가 background-tap(다른 탭)이거나, 최소화 된 창의 일부이거나, OS 화면 잠금이 활성 상태임을 의미.
Document.visibilityState
의 값이 변경되면 visibilitychange
이벤트가 발생하여 웹 페이지 가시성에 따른 동작을 처리할 수 있다.
즉, visibilitychange
이벤트를 통해 Document.visibilityState
의 변경을 감지한다.
Usages
// 1. addEventListener()에 이벤트 이름 전달하기
document.addEventListener('visibilitychange', (event) => {
console.log(document.visibilityState);
});
// 2. 이벤트 처리기 속성 사용하기
document.onvisibilitychange = (event) => {
console.log(document.visibilityState);
};
React에서 사용하기
React에서 웹 가시성 로직을 구현하기 위해서 useEffect
를 활용한다.
useEffect(() => {
const handleVisibilityChange = () => {
// 페이지 복귀
if (document.visibilityState === 'visible') {
console.log('복귀');
}
// 페이지 이탈
if (document.visibilityState === 'hidden') {
console.log('이탈');
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
// 메모리 누수 방지
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}, []);
컴포넌트 라이프사이클 중 언마운트 시에 이벤트 제거를 통해 이벤트가 반복적으로 쌓이는 문제를 방지한다.
Custom hook
이를 활용해 React에서 웹 가시성 상태를 출력하는 커스텀 훅을 만들 수 있다.
usePageVisibility.ts
import { useEffect, useState } from 'react';
type VisibilityState = 'visible' | 'hidden';
const usePageVisibility = <VisibilityState>() => {
const [visibilityStatus, setVisibilityStatus] = useState(document.visibilityState);
useEffect(() => {
const handleVisibilityChange = () => {
setVisibilityStatus(document.visibilityState);
};
document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}, []);
return { visibility: visibilityStatus };
};
Usage of usePageVisibility.ts
const MyComponent = () => {
const { visibility } = usePageVisibility();
return (
<div>
<p>Current visibility state: {visibility}</p>
</div>
);
};
Footnotes
-
눈에 띄는 정도 ↩