[React-Query]useInfiniteQuery와 getNextPageParams

트릴로니·2022년 10월 5일

react-query

목록 보기
1/1

unsplash API를 사용해서 갤러리 어플리케이션을 만들고 있다. 리액트의 useInfinteQuery를 사용하면 인피티티 스크롤을 쉽게 만들 수 있는데 문제는 unsplash API에서 응답 데이터에 총 페이지 개수는 주지만 현재 페이지나 다음 페이지가 있는지 없는지와 같은 페이지와 관련된 다른 데이터는 주지 않는다. 그래서 다음 페이지의 정보를 인피니티 스크롤로 받기 위해 따로 데이터를 넣어줘야 한다.

  • 이미지 검색 기능을 쓰고 쓰고싶어서 처음에는 searchUrl 요청 api를 하나만 썼다. 그러나 이 api는 검색어가 없으면 이미지 데이터를 따로 주지 않아서 이 api로만 쓰면 메인페이지에 빈 페이지가 되었다.

  • 처음에 들어갔을 때 핀터레스트 처럼 랜덤한 이미지가 띄워져 있었으면 좋을 것 같아서 랜덤한 이미지를 제공하는 api도 사용하기로 했다.

  • 그러나 두 api가 주소도 다르고 받는 param도 달라서 컴포넌트를 따로 분리해야 될 까 싶었지만 유지보수 하기도 좋을 것 같고 코드 양도 줄일겸 if문으로 만약 key(검색어이다)가 있으면 serachUrl을 없으면 defaultUrl(렌덤이미지)로 요청을 하도록 했다.

  • key는 검색어로 유니크하기 때문에 react-query를 쓰는데는 문제가 없었다.

  • return 값으로 응답받은 이미지 데이터 말고도 몇가지를 설정해 줘야 했다.

  1. page: unsplash API는 현재 페이지 정보나 다음 페이지가 있는지 없는지 같은 페이지에 관한 정보가 없어서 현재 페이지가 몇페이지 인지 반환 객체에 넣어주었다. 이 데이터는 useInfiniteQuery의 getNextPageParam에서 쓰인다.
const searchUrl = "https://api.unsplash.com/search/photos?";
const defaultUrl = "https://api.unsplash.com/photos/random?";
let url;
let params;

const fetchUrl = async (key , pageNum) => {
  if(key.length > 0){
    console.log(pageNum);
    url = searchUrl;
    params = {
      query: key,
      page: pageNum,
      client_id: process.env.REACT_APP_UNSPLASH_KEY,
    };
  } else {
    url = defaultUrl;
    params = {
      count: 10,
      client_id: process.env.REACT_APP_UNSPLASH_KEY,
    }
  }

  const response = await axios.get(url,{params});

  if(key.length > 0){
    return {...response.data, page: pageNum, isSearch: true};
  } else {
    return {
      results: [...response.data],
      page: pageNum,
      isSearh: false,
    }
  }
}
  const {data = {}, fetchNextPage, hasNextPage, isFetching, isLoading} = useInfiniteQuery(['page', searchTerm], 
  ({queryKey , pageParam = 1}) => fetchUrl(queryKey[1], pageParam), 
  {
    getNextPageParam: (lastPage) => {
      if(lastPage.isSearch){
        const {page, total_pages: totalPages} = lastPage;
        return (page < totalPages) ? page + 1 : undefined;
      } else {
        const {page} = lastPage;
        return page + 1;
      }
    }
  })
  • 위 코드에서 반환값에 현재 페이지가 몇 페이지인지 직접 넣어줬는데 이 값을 만약 unsplash API가 주는 데이터는 total_pages보다 작으면 page+1을 해주고 아니면 undefined를 반환하도록 했다

  • 이렇게 하면 다음 페이지가 undefined인 경우 hasNextPage가 false가 되고 마지막 페이지 이후 요청이 안가도록 만들어 줄 수 있다.

  • undefined가 아닌경우 fetchNextPage에 다음 페이지의 요청 주소가 설정된다.

  • 이 프로젝트의 경우 따로 인피니티 스크롤을 구현하지 않고 react-infinite-scroller를 사용했는데 hasMore과 loadMore을 prop으로 받는다.

<InfiniteScroll loadMore={fetchNextPage} hasMore={hasNextPage}>
        <ImgContainer>
          ...
        </ImgContainer>
</InfiniteScroll>

0개의 댓글