[ React ] 15초 후 다음 페이지로 자동 이동 기능
구현하고자 하는 것
위 gif처럼, 피드 아래 상태표시줄 같은 progressbar가 존재하고, 특정 시간이 지나면, 랜덤으로 다음 피드로 이동한다.
먼저, 백엔드에서 랜덤으로 피드를 넘겨줄 수 있는 getRandomDiary가 있다고 가정할 경우에 해보겠다.
프로그레스바 생성
https://ant.design/components/progress
Progress - Ant Design
An enterprise-class UI design language and React UI library with a set of high-quality React components, one of best React UI library for enterprises
ant.design
ant design의 progress 컴포넌트를 사용하여 UI를 구성했으며, 시간을 15초로 지정했다.
import { useState, useEffect } from "react";
import { Progress } from "antd";
const ProgressBar = () => {
const SEC = 15; // 15초 후 다음 피드로 지나감
const [percent, setPercent] = useState(0);
useEffect(() => {
// 프로그레스 바의 증가량을 계산, 1000ms = 1초
const totalMilliseconds = SEC * 1000; // 전체 시간을 밀리초로 변환
const intervalMilliseconds = 150; // 인터벌 시간을 밀리초로 설정
const progressIncrement = 100 / (totalMilliseconds / intervalMilliseconds); // 진행률 증가량 계산
const interval = setInterval(() => {
setPercent((prevPercent) => {
if (prevPercent >= 100) {
clearInterval(interval); // 진행률이 100%에 도달하면 인터벌 정리
return 100;
}
return prevPercent + progressIncrement;
});
}, intervalMilliseconds);
// 컴포넌트가 언마운트되거나, 재렌더링 되기 전에 인터벌을 정리
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className="fixed bottom-[56px] left-[50%] z-20 flex w-full -translate-x-1/2 transform align-bottom custom-breakpoint:w-[450px] ">
<Progress
percent={percent}
strokeColor={"#FF6D3C"}
showInfo={false}
strokeLinecap="square"
size={"small"}
style={{ margin: 0 }}
/>
</div>
);
};
export default ProgressBar;
그러면 위처럼 15초가 되면 멈추는 프로그레스 바가 생성된다.
내가 필요한 것은 15초 후 다음 피드로 자동 이동하는 것이다.
- getRandomDiaryId.ts
import axios from "axios";
export const getRandomDiaryId = async () => {
try {
const response = await axios.get<{ diary_id: string }>(`/api/diary/random`);
if (response.data) {
return response.data.diary_id;
}
} catch (e) {
console.error;
}
};
그리고 위를 호출하는 함수 fetchNextDiary를 Progress바 컴포넌트 파일 안에 선언한다.
diary_id값을 받아오고, 해당 아이디를 엔드포인트로 하는 피드페이지로 이동한다.
const fetchNextDiary = async () => {
try {
const data = await getRandomDiaryId();
if (data) {
navigate(ROUTE.FEED_DETAIL_PAGE.link + `/${data}`, {
state: { toNext: true },
});
}
} catch (error) {
console.error(error);
}
};
그 후 prevPercent가 100이 되었을 경우에 fetchNextDiary를 호출한다.
const interval = setInterval(() => {
setPercent((prevPercent) => {
if (prevPercent >= 100) {
clearInterval(interval); // 진행률이 100%에 도달하면 인터벌 정리
fetchNextDiary();
return 100;
}
return prevPercent + progressIncrement;
});
}, intervalMilliseconds);
위처럼 15초가 경과되면, 주소값이 바뀌고, 해당하는 피드 데이터가 잘 보여진다.
에러 상황
랜덤으로 다음 피드를 추천하기 때문에 이미 나왔던 것을 또 추천할 수도 있는데,
해당 프로그레스바가 이미 종료되었고, 그 상태가 유지되기 때문에 프로그레스바가 0부터 시작되지 않는 것이다.
해결방법으로서, 페이지의 url이 바뀌면 프로그레스 바가 초기화되도록 코드를 추가해주었다.
const location = useLocation();
// ...
useEffect(() => {
setPercent(0);
// ...
}, [location.pathname]);
이제는 전에 나온 피드가 또 나와도 프로그레스 바가 0부터 잘 시작된다 !