DEVELOP
article thumbnail

1. 구현하고자 하는 것

위 gif처럼, 피드 아래 상태표시줄 같은 progressbar가 존재하고, 특정 시간이 지나면, 랜덤으로 다음 피드로 이동한다. 

먼저, 백엔드에서 랜덤으로 피드를 넘겨줄 수 있는 getRandomDiary가 있다고 가정할 경우에 해보겠다. 

 

2. 프로그레스바 생성

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초로 지정했다. 

<typescript />
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

<typescript />
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값을 받아오고, 해당 아이디를 엔드포인트로 하는 피드페이지로 이동한다. 

<typescript />
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를 호출한다. 

<typescript />
const interval = setInterval(() => { setPercent((prevPercent) => { if (prevPercent >= 100) { clearInterval(interval); // 진행률이 100%에 도달하면 인터벌 정리 fetchNextDiary(); return 100; } return prevPercent + progressIncrement; }); }, intervalMilliseconds);

위처럼 15초가 경과되면, 주소값이 바뀌고, 해당하는 피드 데이터가 잘 보여진다. 

3. 에러 상황

랜덤으로 다음 피드를 추천하기 때문에 이미 나왔던 것을 또 추천할 수도 있는데,

해당 프로그레스바가 이미 종료되었고, 그 상태가 유지되기 때문에 프로그레스바가 0부터 시작되지 않는 것이다. 

해결방법으로서, 페이지의 url이 바뀌면 프로그레스 바가 초기화되도록 코드를 추가해주었다.

<typescript />
const location = useLocation(); // ... useEffect(() => { setPercent(0); // ... }, [location.pathname]);

 

이제는 전에 나온 피드가 또 나와도 프로그레스 바가 0부터 잘 시작된다 ! 

profile

DEVELOP

@JUNGY00N