I am trying to integrate pagination in my react native app. I am able to get all the data
api response:
{"msg": "shifts list","data": {"docs": [ {"_id": "1","expected": {"shift_duration_minutes": 120,"shift_end_time": "2022-01-01T15:30:00.000Z","shift_start_time": "2022-01-01T13:30:00.000Z" }, } {"_id": "2","expected": {"shift_duration_minutes": 120,"shift_end_time": "2022-02-01T17:30:00.000Z","shift_start_time": "2022-02-01T19:30:00.000Z" }, } ........so on until id number 20 ],"page": 1,"limit": 5,"pages": 4,"total": 20 },"success": true}
I am maintaining few states:
const [isLoading, setIsLoading]: any = useState(true);const [isLoaded, setIsLoaded]: any = useState(false);const [shift, setShift] = useState<ShiftsList[] | null>(null);const [pagination, setPagination] = useState<PaginationType | null>(null);
my api call function:
const getShiftDetails = useCallback( (page = 1, limit = 5) => { setIsLoading(true); const payload = {page, limit}; ApiFunctions.post(apiUrl +'shift', payload) .then( async (resp: TSAPIResponseType<PaginationResponseType<any>>) => { setIsLoading(false); setIsLoaded(true); if (resp) { if (resp.success) { const docs = resp.data.docs || []; const paginationObj = resp.data; setShift(prevList => { prevList = prevList || []; if (paginationObj.page === 1) { return docs; } else { return [...prevList, ...docs]; } }); delete paginationObj.docs; setPagination(paginationObj); } else { console.log(resp.error) } } }, ) .catch((err: any) => { setIsLoading(false); setIsLoaded(true); console.log(err); }); }, [],);
my load next page function:
const loadNextPage = useCallback(() => { console.log('next page ....', pagination); let page = 1; if (pagination) { page = pagination.page || 1; page++; const pages = Math.ceil(pagination.total / pagination.limit); if (pages >= page) { console.log('loading page ....', page); getShiftDetails(page); } }}, [pagination, getShiftDetails]);
Finally I am using FlatList to display all the data:
<> {isLoading && <ActivityIndicator/>} {!isLoading && isLoaded && !shift && <ErrorComponent />} {!isLoading && isLoaded && shift && (<><View style={{flexGrow: 1}}><FlatList data={shift} onRefresh={getShiftDetails} refreshing={isLoading} onEndReached={loadNextPage} ListFooterComponent={<> {isLoading && (<><View><ActivityIndicator/></View></> )}</> } onEndReachedThreshold={0.7} renderItem={({item}) => { return (<View><MyShiftComponent id={item._id} shiftStartTime={item.expected.shift_start_time} shiftEndTime={item.expected.shift_end_time} /></View> ); }} /></View></> )}</>
So now all the data of page keeps on loading until all data are displayed on screen. For example, "page": 1,
has 5 data, so those 5 would load, then <ActivityIndicator/>
will come on screen and immediately next "page": 2
will load, and this will go on untill all the data are displayed on screen.
What I wanted is that, next page data should load when the screen is scrolled to certain length, that too my whole screen should not show <ActivityIndicator/>
, only ListFooterComponent
should come.