DEVELOP
article thumbnail

구현하고자 하는 것

위 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부터 잘 시작된다 ! 

profile

DEVELOP

@JUNGY00N