SWR 무한 스크롤 코드 리뷰하기

Imnottired·2023년 5월 2일
0
post-thumbnail

이번에 무한 스크롤 구현하기로 하였다.

코드를 직접 작성하고 추가하는 식으로 추가하려고 하였지만,

SWR 공식 문서를 보던 중, ReactQuery 와 같은 방식으로 구현하는 것이 있어서 활용하게 되었다.

활용하는 이유는 2가지이다.

1번째는 라이브러리를 설치하였어서 활용도를 높이기 위함이고,

2번째는 캐싱 최적화가 잘되어있어서 그렇다.



SWR 훅 중에
useSWRInfinite 로 하나의 후크를 통해 여러 요청을 트리거할 수 있다.

이를 활용할 것이다.

SWR에서 활용하는 예제를 보면

load more를 클릭하면 데이터를 더 받아오거나 refresh를 통해 데이터를 업데이트할 수 있고,
clear를 통해 초기화 할 수 있다.

또한 인피니티 스크롤이 전부다 사용이 되어지면 알려줄 수도 있다.

한번에 보면 눈이 아파서 분할로 보겠다.
이제 코드를 보자

import useSWRInfinite from "swr/infinite";

const fetcher = (url) => fetch(url).then((res) => res.json());
const PAGE_SIZE = 6;

  const {
    data,
    mutate,
    size,
    setSize,
    isValidating,
    isLoading
  } = useSWRInfinite(
    (index) =>
      `https://api.github.com/repos/${repo}/issues?per_page=${PAGE_SIZE}&page=${
        index + 1
      }`,
    fetcher
  );


먼저 useSWRInfinite 훅을 부르고, 첫번째 인자로는 url를 두번째인자에는 fetch를 처리할 콜백함수를 넣어주면 된다.

차례대로 리턴하는 값들을 보면

  • data는 요청으로 받아온 데이터를 담고있는 변수

  • mutate는 데이터를 업데이트하는 함수이다. 새로운 데이터를 렌더링하게 도와준다.

  • size는 요청에서 가지고온 데이터의 갯수를 알려준다.

  • setSize는 다음 요청에서 가져올 데이터 갯수를 설정하는 함수입니다.

  • isValidating SWR이 데이터를 요청하는 중이거나 데이터를 검증하고 있는 동안 true를 반환합니다

  • isLoading은 실제로 데이터를 받아오는 중인 동안에만 true를 반환합니다.


  const issues = data ? [].concat(...data) : [];
  // 데이터
  
  const isLoadingMore =
    isLoading || (size > 0 && data && typeof data[size - 1] === "undefined");
  //로딩중인지?
  const isEmpty = data?.[0]?.length === 0;
  // 비어있는지?
  const isReachingEnd =
    isEmpty || (data && data[data.length - 1]?.length < PAGE_SIZE);
  // 요청할 데이터가 더없는지?
  const isRefreshing = isValidating && data && data.length === size;
  // 데이터를 요청 중인지?
  

순서대로 주석으로 확인할 수 있다.

이제 JSX코드를 보면


 <div style={{ fontFamily: "sans-serif" }}>
    <input
      value={val}
      onChange={(e) => setVal(e.target.value)}
      placeholder="reactjs/react-a11y"
    />
    <button
      onClick={() => {
        setRepo(val);
        setSize(1);
      }}
    >
      load issues
    </button>
    <p>
      showing {size} page(s) of {isLoadingMore ? "..." : issues.length}{" "}
      issue(s){" "}
      <button
        disabled={isLoadingMore || isReachingEnd}
        onClick={() => setSize(size + 1)}
      >
        {isLoadingMore
          ? "loading..."
          : isReachingEnd
          ? "no more issues"
          : "load more"}
      </button>
      <button disabled={isRefreshing} onClick={() => mutate()}>
        {isRefreshing ? "refreshing..." : "refresh"}
      </button>
      <button disabled={!size} onClick={() => setSize(0)}>
        clear
      </button>
    </p>

  </div>
  

이러하다 Val를 통해 타이핑한 데이터를 업데이트를 하고,
검색할 데이터가 변경된다면, Repo를 통해 업데이트를 한다.

load issues라는 버튼을 눌렀을 때 setSize를 불러와서 다시한번 요청을하고,

사이즈를 통해 요청 횟수를 알 수 있다.

refresh버튼을 통해 최신 업데이트를 하고,

clear를 눌러 setSize(0) size를 지워버릴 수도 있다.


   {isEmpty ? <p>Yay, no issues found.</p> : null}
   {issues.map((issue) => {
     return (
       <p key={issue.id} style={{ margin: "6px 0" }}>
         - {issue.title}
       </p>
     );
   })}
   

마지막으로 밑에 데이터를 채우거나 없으면 알려주는 text로 마무리가 된다.

이를 통해 무한 스크롤을 상황에 맞추어 구현할 수 있다.




마무리

인피니티 스크롤 로직을 활용해서 이상형월드컵에 넣을 생각이다.
이 로직을 보면서 인상깊었던 것은 이를 구현한 것보다 로직을 작성하는 생각들이 인상적이었다.
수많은 시행착오를 겪고, 그러한 경험들이 로직에서 느껴져서 좋았다.

  const isLoadingMore =
    isLoading || (size > 0 && data && typeof data[size - 1] === "undefined");
  const isEmpty = data?.[0]?.length === 0;
  const isReachingEnd =
    isEmpty || (data && data[data.length - 1]?.length < PAGE_SIZE);
  const isRefreshing = isValidating && data && data.length === size;

경우의 수를 예측하여 변수의 조건을 작성하는 것이 인상깊었다.
논리 연산자를 사용하여서 깔끔하게 경우의 수를 고려하여서 작성한 것이 좋았다.

또한 onChange 값을 바로 연결하는 것이 아니라, 트리거하는 상황에 맞추어 넣어주는 방식도 좋았다.
useState 2개를 사용하여서 1개는 저장용 나머지 1개는 넣어주는 용도로 분리하여서 통제가 한결 쉬워보였다.

다음에는 참고하여서 활용하여야겠다.
그리고 코드리뷰를 블로그에 처음 작성해보는데 확실히 정리가 잘되었고, 이해도가 높아진거 같아서 종종 블로그에 남겨야겠다.

출처
https://swr.bootcss.com/examples/infinite-loading.html

profile
새로운 것을 배우는 것보다 정리하는 것이 중요하다.

5개의 댓글

comment-user-thumbnail
2023년 5월 6일

이상형 월드컵 기대됩니다 !!

답글 달기
comment-user-thumbnail
2023년 5월 7일

글 보면 항상 많이 고민하신 것이 느껴져서 이상형 월드컵이 더 기대됩니다 ㅎㅎ

답글 달기
comment-user-thumbnail
2023년 5월 7일

빨리 완성하신 프로젝트를 보고싶네용!

답글 달기
comment-user-thumbnail
2023년 5월 7일

SWR만의 문법이 따로 있군요! 과연 어떨 완성작이 나올지 두근두근

답글 달기
comment-user-thumbnail
2023년 5월 7일

리액트쿼리로 무한스크롤 구현해본 적이 있는데 useSWRInfinite도 있었군요,, 이것도 재밌는거 같습니다

답글 달기