화면에서 일정시간동안 입력이 없으면 메인화면으로 전환되는 기능이 필요했다. 기능을 구현하기 위해 아래와 같은 커스텀 훅을 만들었다.
useEventTimeout
지정한 이벤트의 발생으로부터 일정 시간 이후에 콜백 함수를 실행시킨다.
먼저, 파라미터로 다음과 같은 값을 받았다.
callback
: 콜백 함수events
: 트리거를 발생시킬 이벤트 이름 리스트timeout
: 콜백 함수의 실행 딜레이 시간
이때 기본값으로 events
는 사용자의 입력을 감지하기 위해 click
과 keypress
이벤트를 설정했고 timeout
은 5분으로 지정하였다.
구현은 Debounce
와 동일한 개념으로 개발하였다.
일단, debounced value
를 저장하기 위한 state를 선언했다.
const [idleTime, setIdleTime] = useState(new Date());
다음으로, 파라미터로 받은 events
에 listener
를 등록해주었다. 해당 listener
는 이벤트가 발생할 때마다 debounced value
의 값을 새로 세팅해준다. 이때, useEffect
의 cleanup
함수를 이용하여 새로운 이벤트 리스너를 등록하기 전에 이전에 등록한 이벤트 리스너를 제거해주었다.
const resetTimer = useCallback(() => {
setIdleTime(new Date());
}, []);
useEffect(() => {
events.forEach((event) => {
window.addEventListener(event, resetTimer);
});
return function cleanup() {
events.forEach((event) => {
window.removeEventListener(event, resetTimer);
});
};
}, []);
마지막으로, timeout
으로 지정한 시간 뒤에 callback
함수를 호출하도록 해주었다. 이때 debounced value
또는 timeout
시간이 변경되면 기존에 등록한 setTimeout
을 제거하고 다시 생성한다. 이를 통해 지정한 시간 이내에 debounced value
의 변경이 이루어진다면 기존에 등록한 setTimeout
에서의 콜백 함수 호출을 방지한다. 즉, setTimeout
을 통해 콜백 함수가 호출되는 시점은 가장 마지막에 발생한 이벤트를 기준으로 지정한 timeout
시간이 지난 시점이다.
useEffect(() => {
const idleTimer = setTimeout(() => {
callback();
}, timeout);
return function cleanup() {
clearTimeout(idleTimer);
};
}, [idleTime, timeout]);
전체 코드는 다음과 같다.
import { useCallback, useEffect, useState } from 'react';
const idleTimeout = 1000 * 5; // 5 minutes
const useEventTimeout = (
callback: () => void,
events: string[] = ['click', 'keypress'],
timeout: number = idleTimeout
) => {
const [idleTime, setIdleTime] = useState(new Date());
const resetTimer = useCallback(() => {
setIdleTime(new Date());
}, []);
useEffect(() => {
events.forEach((event) => {
window.addEventListener(event, resetTimer);
});
return function cleanup() {
events.forEach((event) => {
window.removeEventListener(event, resetTimer);
});
};
}, []);
useEffect(() => {
const idleTimer = setTimeout(() => {
callback();
}, timeout);
return function cleanup() {
clearTimeout(idleTimer);
};
}, [idleTime, timeout]);
};
export default useEventTimeout;
사용 예시
사용자의 입력이 5분동안 발생하지 않으면 메인화면으로 전환되어야 하므로 아래와 같이 커스텀 훅을 사용했다.
// import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
useEventTimeout(() => navigate('/'));
'정리용' 카테고리의 다른 글
useLayoutEffect (0) | 2022.09.22 |
---|---|
React Query의 InvalidateQueries가 동작하지 않을 때 (1) | 2022.09.14 |
크롬에서 막혀있는 포트 (0) | 2022.07.01 |
Proxy 서버로 CORS 해결하기 (0) | 2022.06.24 |
Docker 명령어 정리 (0) | 2022.05.25 |