[React] - 방명록을 만들어보자!

장광진·2024년 3월 7일


플레이리스트의 방명록을 만드려면 이러한 UI의 방명록이 필요했다. 헤더를 고정할 필요는 없지만 사용자가 스크롤을 내리지않고 항상 댓글을 입력해야하므로, Footer는 항상 고정해야했다.


1. 댓글 영역과 작성 영역 고정하기(Feat. 무한스크롤)

댓글이 보여지는 부분은 무한스크롤을 구현하여 처리하고 Footer는 항상 고정해야 한다. 처음에는 헤더와 푸터의 높이를 각각 10%씩 지정하여 Main의 height를 80%로 하거나, Px단위로 바꾸어 적용도 해보았지만 height가 고정되는 순간 안의 데이터들이 짤려버리는 문제가 발생했다. 또한 댓글이 길어지면 Div의 height도 계속 바뀌기 떄문에 고정 height를 쓸 수 없었다. 끝없는 구글링결과 나는 두가지 라이브러리를 사용하기로 했다 ㅎ.. 바로 react-intersection-observer와 InfinityScroll이다!

npm i react-intersection-observer
npm i react-infinite-scroller

요렇게 두가지 라이브러리를 깔아주자.

<InfiniteScroll
          className="h-[85%] smartPhone:h-[70%] overflow-y-scroll scrollbar-hide"
          pageStart={0}
          loadMore={loadMore}
        >
          <main>
            <div className="flex flex-col items-center justify-center h-full">
              {visitorData &&
                visitorData.map((visitor: any) => (

헤더와 푸터는 각각 5%, 10%의 height를 가지고 있어 InfiniteScroll을 85%로 선언해주었다. 이때 InfiniteScroll은 pageStart와 loadMore는 필수적으로 작성해야하는 props로 pageStart는 0번 page부터 데이터를 보여주므로 0으로 설정해주고 loadMore는 스크롤을 내릴떄 동작하는 함수인데 나는 굳이 필요없으므로 laodMore라는 빈 함수를 넣어주었다.

그럼 요롷게 범위안에서 스크롤을 내리지 않는 무한스크롤이 되었다! 근데 이러면 끝난거아닌가?라는 생각이 들 수 있지만 그렇지 않다. 왜냐하면 15개씩 페이징이 되어있어서 버튼을 누르면 추가적인 페이지가 렌더링되도록 해야하기 떄문이다 ㅠㅠㅠㅠㅠ..


2. 버튼으로 추가 페이지 렌더링

업로드중..
요렇게 댓글이 15개가 넘어가면 버튼으로 추가 렌더링을 하도록 해주자. 지금이야 댓글이 얼마 없지만 예를들어 300개라면 한번에 300개 이상의 데이터가 렌더링되어 성능이 저하될것이다. 또한 사용자들도 굳이 300개를 전부 보고싶어하지도 않을것이다! 그래서 백엔드에서 15개씩 페이징을 해주었다 ㅎㅎ

import { useInView } from "react-intersection-observer";
const Visitor = () => {
  const [view] = useInView(); // view에 도달했을떄 새로운 페이지 렌더링

  const [isLast, setLast] = useState<boolean>(false); //
  const [page, setPage] = useState<number>(0);
  const [visitorData, setVisitorData] = useState<VisitorData[]>([]);
  
  
  const fetchVisitorData = async (pageNum: number) => {
    try {
      const visitor = await getVisitor(Number(playlistId), pageNum);
      setVisitorData((prevUsers) => [...prevUsers, ...visitor.data]);

      if (visitor.data.length < 15) { // 15개 미만일떄
        setLast(true); // true로 바꿔주자.
      } else {
        setLast(false);
      }
    } catch (error) {
      console.error(error);
    }
  };
  
  const handleLoadMore = () => {
    const newPage = page + 1;
    setPage(newPage); // 페이지 번호를 증가시키고
    fetchVisitorData(newPage); // 새 페이지 번호를 fetchVisitorData에 전달
  };
  return(
    {!isLast && (
            <button
              onClick={handleLoadMore}
              className="flex justify-center items-center h-10 w-full"
            >
              <FaCirclePlus size={28} color="" />
            </button>
          )}

isLast가 false일때 버튼을 누르면 handleLoadMore 함수가 실행된다. 페이지를 증가시키고 새 페이지에대한 api를 요청하는 구조이다. 이로써 처음엔 0페이지에서 추후에 페이지를 증가시키며 데이터를 렌더링하는 것이다.

profile
점진적 과부하

0개의 댓글