react-query useInfiniteQuery

반응형

 

infinite scroll 을 구현하는 경우 useQuery 로는 대응이 안된다.

 

infinite scroll 의 경우 page 가 한개씩 늘어나면서 늘어난 page 가 데이터에 추가되는 식이다.

참고로 pagination 은 새로운 page 로 데이터가 갱신된다.

react-query 는 useQuery, useInfiniteQuery 를 대표적으로 사용한다. pagination 은 useQuery 로 대응한다.

 

https://react-query.tanstack.com/reference/useQuery

https://react-query.tanstack.com/guides/paginated-queries

https://react-query.tanstack.com/guides/infinite-queries

 

useInfiniteQuery 의 경우 리턴받는 상태값 중에 data 가 있는데 data?.pages 에 axios 나 fetch 로 받은 데이터들이 하나씩 들어 있다.

pages = [page, page, page, ...] 이런식이다. hasNextPage 도 리턴이 받아지는데 undefined 리턴시에는 nextPage 가 없다고 인식한다. 따라서 서버 응답으로 totalCounts 라던가 totalPages 같은 값이 존재해야할 수 있다. api 설계 단 부터 pagination 과 유사하게 고려되어야 한다.

 

간단할 것 같지만 실제 적용에는 조금 어려움이 있다. 단순히 react-query 의 예제처럼 nextCursor 즉 다음 +1 페이지씩만 하는 것이 아니라 보통은 검색 조건에 따른 필터도 적용될 수 있고 또한 각 axios 요청에 대한 응답 즉 page 의 경우 보통은 서버 응답값으로 data 외에 서버 자체의 resultCode, resultMessage 를 내려주기도 하기 때문에 이러한 부분에 대한 가공이 이루어질 수도 있다. page 구성을 위한 데이터 가공은 되지만 resultCode, resultMessage 에서 커스텀 지정한 오류코드 같은 것을 응답할 경우 어떻게 대응할 수 있을까?

 

적어도 요청을 하는 axios 같은 api 자체는 react-query 의 방식을 고려하여 설계할 수는 있어도 의존적이지 않아도 사용할 수 있어야 한다. 그렇지 않으면 react-query 의 사용성은 떨어진다고 봐야한다.

 

react-query 는 함수형 방식이라고 볼 수 있다. 기존처럼 axios 요청을 보내고 받고 그에 대한 응답 처리를 하는 imperative 한 방식과는 다른다. 그리고 어느정도 정해진 틀이 있다. 그 정해진 틀에 따라 조립하는 식으로 다가가야 한다. getNextPageParam, fetchNextPage, 그리고 요청 함수의 리턴값을 통해 충분히 자유도 있게 구성은 가능하다. 방금 전 언급한 resultCode, resultMessage 에 대한 대응의 경우 요청 함수의 리턴값을 만드는 useInfiniteQuery('queryKey', queryFn, options) 중 queryFn 에서 함수형 처럼 이벤트 형식으로 붙여주는 것도 좋아보인다. 기존 imperative 하게는 처리하기 어려워 보인다.

 

이미 정해진 틀에서 data 라는 상태값을 리턴으로 받아서 사용하기 때문에 react-query 방식의 틀에서 개발해야 한다. data 에 Reactive 하게 필터링을 적용하여 대응은 할 수 있을 것이다. 관계형 데이터베이스에서 users { id, name, Images, Posts } 같은 nested 된 데이터를 응답으로 받았다고 할 경우 어느정도의 정규화를 고려하여 기존의 imperative 하게 응답값에 대해서 각각 users[], images{ids, entities}, posts {ids, entities} (https://redux.js.org/usage/structuring-reducers/normalizing-state-shape) 와 같이 상태값을 만들어서 하는 식으로는 개발이 어려울 듯 하다. 함수형 방식으로 data.map.reduce.filter.... 와 같은 식으로 대응해야 할 것으로 보인다. 

 

이러한 캐싱기법은 과거에는 에어비앤비 같은 큰 기업들이나 사용할 수 있었던 매우 고급 기술이었다. 그런데 이렇게 리덕스로 치면 툴킷과 같이 best practice 가 정리되어 react-query, swr, rtk-query 라는 오픈소스로 제공되어 어느정도 쉽게 다가갈 수 있도록 해주었다. 해당 라이브러리의 틀에 맞추어 개발을 해야하기에 조금 불편감은 있을 수 있지만 production 레벨의 서비스에서는 매우 큰 이점이 있도록 해준다. 결국 고도화해 나가다 보면 react-query 같은 것을 만들어가고 있을 것이다.

 

사용할 수 있다면 최대한 사용하는 방향이어야 하겠지만 매우 유동적으로 커스텀이 필요한 코드에 무조건 react-query 같은 것을 강제할 필요는 없다. 최대한 활용하면 성능향상과 클린 코드로 사용할 수 있지만 해당 라이브러리의 틀에 맞지 않는 경우 어쩔 수 없이 직접 axios 를 사용한 요청을 통한 개발을 해야할 수도 있다. 그리고 전역 상태 관련하여 toolkit 과 함께 rtk-query 의 사용은 꽤나 유용할 것 같다.

 

react-query 는 최근에 v3 으로 업데이트 되었다. 많이 달라졌으니 과거 v2 소스와 구분하여 참고해야 한다. (2021/10/05 기준)

 

[리액트 웹에서 infinite scroll 구현] react-query v3

https://www.youtube.com/watch?v=ASlTFtCjkU8 

https://gist.github.com/ivandoric/2f770c7b8c165d76a431e34c98312d76

 

[리액트 네이티브에서 infinite scroll 구현] << 이건 구버전 react-query v2 로 작성되어 있다. v3 에서는 많이 바뀌었으니 참고만.

https://www.youtube.com/watch?v=wvWWija8mNM 

https://gist.github.com/jonasgroendahl/527a41a38ab67869ed798461940f147d

 

[react-query infinite scroll 공식 예제] react-query v3

https://react-query.tanstack.com/examples/load-more-infinite-scroll

 

[react-query infinite scroll 설명 한국어] react-query v3

https://shindongri.dev/blog/react-query-10/

 

[react-query infinite scroll 소스 참고] react-query v3

https://blog.prasanna.codes/how-to-implement-infinite-scrolling-in-react

 

[react-query infinite scroll 설명 한국어] << 이건 구버전 react-query v2 로 작성되어 있다. v3 에서는 많이 바뀌었으니 참고만.

https://velog.io/@alvin/Referring-3.-Infinite-Scroll-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0

해당 블로그의 좋은 글. 빈 객체 타입 정의. https://velog.io/@alvin/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%B9%88-%EA%B0%9D%EC%B2%B4-%EC%A0%95%EC%9D%98%ED%95%98%EA%B8%B0

 

[react-query infinite scroll 또 다른 예제]  << 이건 구버전 react-query v2 로 작성되어 있다. v3 에서는 많이 바뀌었으니 참고만.

https://codesandbox.io/s/tiihm?file=/src/index.js 

 

 

optimistic update

https://github.com/tannerlinsley/react-query/blob/171628699cff8e6bbfa5d31bc3d1ccb11ff9e12f/examples/optimistic-updates/pages/index.js#L43-L46

반응형

댓글

Designed by JB FACTORY