일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 사이드프로젝트
- Instagrame clone
- selenium
- 조코딩
- 크롤링
- 전국국밥
- kaggle
- expo
- React
- JavaScript
- App
- 정치인
- clone coding
- FirebaseV9
- TeachagleMachine
- 강화학습 기초
- pandas
- ReactNative
- 딥러닝
- python
- 머신러닝
- 클론코딩
- 앱개발
- 데이터분석
- 카트폴
- 강화학습
- redux
- 리액트네이티브
- coding
- Ros
- Today
- Total
qcoding
[ReactNative_Study_11]무한스크롤 구현 (Flat List & React query) 본문
FlastList & React query 사용하여 무한 스크롤을 구현한다.
1) Flat List
--> FlastList props 중에서 onEndReached , props를 사용한다.
<FlatList
// 무한스크롤 구현시 사용하는 props
// Threshold에 도달했을 때 실행되는 함수가 onEndReached가 된다.
onEndReached={}
onEndReachedThreshold={}
onRefresh={}
refreshing={}
ListHeaderComponent={}
data={}
keyExtractor={}
ItemSeparatorComponent={}
renderItem={}
/>
2) React Query
--> react query에서 infinitie-queries를 사용한다.
2-1 ) Fetch 시에 기존에 data 받아오는 구조 변경하기
https://react-query.tanstack.com/guides/infinite-queries
--> 기존에 data를 fetch할 때 useQuery() 를 사용하였는데 여기서 fetch후 받아오는 trendingData의 경우 {} Object의 형태를 갖는 것이 useInfiniteQuery ()와는 다르다.
const {isLoading:trendingLoading,data:trendingData,
isRefetching:trendingRefetching}=useQuery(['movies','trending'],moviesApi.trending
ex) useQuery() 의 경우
Object {
"page": 1,
"results": Array []
}
useInfiniteQuery 의 경우
Object {
"pageParams": Array [
undefined,
],
"pages": Array [
Object {
"dates": Object {
"maximum": "2022-01-01",
"minimum": "2021-12-05",
},
"page": 1,
"results": Array []
}
]
로 여기서 results 안에 우리가 필요한 내용들이 배열로 들어가 있다. 즉 동일하게 results를 가져오려면
data={upComingData.pages.map((page)=>{ return (page.results)}).flat()}
로 가져와야 된다. 마지막 flat()이 씌여진 이유는 [ [ ] ] pages에서 map을 사용하므로 배열안에 배열이 생기된다. 그러므로 [ [ page.result], [page.result], [page.result], [page.result], [page.result] ] 이런식의 자료 구조가 되고 flat()을 이용하여 [ page.result, page.result, page.result, page.result, page.result ] 로 만들어 준다. 즉, 정리하면 Flat list의 data안에는 Array 형태가 들어가야 되므로 flat()을 이용하여 배열내 배열구조에서 내부 배열값을 꺼내준다.
2-2) 실제 infinite scroll 구현하기
-> 2-2-1) useInfiniteQuery 에서 다음 페이지 번호 구하기 / 없을 시 null 반환
const {isLoading:upcomingLoading,
data:upComingData,
isRefetching:upcomingRefetching,
// hasNextPage는 아래의 getNextPageParam에서 return으로 나오는 값이다. (boolean)
// 현재 page에서 +1한 값이 전체페이지 보다 크게되면 null이므로 false반환
// 그렇지 않으면 nextPage 숫자값을 반환하므로 true이다.
hasNextPage,
// fetchNextPage는 hasNextPage가 존재할 때 호출할 수 있는 함수로
// refetch 처럼 다시 함수를 불러오는 것으로 쓰이는 듯
fetchNextPage,
}=useInfiniteQuery(['movies','upcoming'],moviesApi.upcoming,
// useQuery()에서 사용한 option의 형태로 작성되며 여기서 return 된 값은
// moviesApi.upcoming , fetch 함수 호출 시에 인자로 전달된다.
//여기서 last page는 useInfiniteQuery로 받는 data 전체를 의미한다.
// 기본적으로 Api에서 page로 존재하는 숫자값에 +1 더해서 다음페이지가 될때
// Api에 존재하는 total_pages 보다 작으면 다음페이지가 존재하는 것이고
// 크거나 같으면 존재하지 않으므로 null을 반환
{
getNextPageParam: (lastPage) => {
const nextPage = lastPage.page + 1;
return nextPage > lastPage.total_pages ? null : nextPage;
},
}
)
* getNextPagePram에서 lastPage에 받는 값은 위에서 useInfiniteQuery 에서 받은 data값이다.
Object {
"pageParams": Array [
undefined,
],
"pages": Array [
Object {
"dates": Object {
"maximum": "2022-01-01",
"minimum": "2021-12-05",
},
"page": 1,
"results": Array []
}
]
2-2-2 ) useInfiniteQuery(['movies','upcoming'],moviesApi.upcoming, 에서 fetch Api인 moviesApi.upcoming를 불러올 때 getNextPageParam에서 return 값이 fetch 함수에 전달된다.
export const moviesApi = {
// 여기서 전달받은 pageParam은 useInfiniteQuery의 getNextPageParam에서보낸 return 값이다
// 다음페이지가 있으면 그 숫자가 전달되고, 없으면 null이 전달된다.
upcoming : ({pageParam}) =>
fetch(
`${BASE_URL}/movie/upcoming?api_key=${API_KEY}&language=ko-KR&page=${pageParam}`
).then((res) => res.json())
};
2-2-3) hasNextPage가 true일 시 fetchNextPage 함수 수행
// 위에서 getNextPageParam에서 숫자 전달 시 true가 되며, 이 때는 다음페이지가 존재한다는
// 의미이므로 fetchNextPage() 함수를 실행시킨다.
const loadMore=()=>{
if (hasNextPage) {
fetchNextPage();
}
};
// 위에서 onEndReached로 끝에 도달하면 함수를 실행시키며
// onEndReachedThreshold를 두어서 어느 정도 도달하는 지 정의할 수 있다.
<FlatList
onEndReached={loadMore}
onEndReachedThreshold={0.4}
/>
최종적으로 정리하면 useInfiniteQuery를 써서 data를 받아오고 pages 안에 있는 배열을 한개씩 늘려가는 형태로 무한스크롤을 구현한 것이다. useInfiniteQuery를 사용하여 getNextPageParam를 사용하여 다음페이지가 있는 지 없는 지 확인하고 여기서 return 된 값을 api함수의 {pageParam}로 받아온다. ( 변수명 바뀌면 안됨 )
이 값이 null이 아닐 경우 fetchNextPage를 통해서 다음 page를 받아온다.
* api에서 page와 total_page 정보가 있는 경우 이를 사용할 수 있을 듯
// 처음
/*{
"pageParams": [undefined],
"pages": [
{"dates": [Object], "page": 1, "results": [Array], "total_pages": 18, "total_results": 348}
]
}*/
// 두번쨰 next page 불러올 때
/*{
"pageParams": [undefined],
"pages": [
{"dates": [Object], "page": 1, "results": [Array], "total_pages": 18, "total_results": 348}
{"dates": [Object], "page": 2, "results": [Array], "total_pages": 18, "total_results": 348}
]
}*/
// 세번쨰 next page 불러올 때
/*{
"pageParams": [undefined],
"pages": [
{"dates": [Object], "page": 1, "results": [Array], "total_pages": 18, "total_results": 348}
{"dates": [Object], "page": 2, "results": [Array], "total_pages": 18, "total_results": 348}
{"dates": [Object], "page": 3, "results": [Array], "total_pages": 18, "total_results": 348}
]
}*/
'ReactNative' 카테고리의 다른 글
[ReactNative_study_13]PanResponder (스크린 화면 터치감지) (0) | 2021.12.12 |
---|---|
[ReactNative_study_12]Animated 사용법 및 사용규칙 (0) | 2021.12.11 |
[React_Native_Study_10]React query 사용하여 검색기능 활용 (0) | 2021.11.30 |
[ReactNative_Study_9]React_query (0) | 2021.11.28 |
[ReactNative_study_8]ScrollView / Flat List (0) | 2021.11.28 |