1
- import { View , Text } from "react-native" ;
1
+ import { Text , SafeAreaView , View , FlatList , ViewabilityConfig , ViewToken } from 'react-native' ;
2
+ import { useHeaderHeight } from '@react-navigation/elements' ;
3
+ import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs' ;
4
+ import { useInfiniteQuery } from '@tanstack/react-query' ;
5
+ import getNextQuestion from '@/query/getNextQuestion' ;
6
+ import { Image } from 'expo-image' ;
7
+ import { useCallback , useEffect , useState } from 'react' ;
8
+ import { cssInterop } from 'nativewind' ;
9
+ import { SCREEN_HEIGHT , SCREEN_WIDTH } from '@/utils/sizeMatters' ;
10
+
11
+ const blurhash =
12
+ '|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj[' ;
2
13
3
14
export default function Home ( ) {
4
- return < View >
5
- < Text > Home Screen</ Text >
6
- </ View >
7
- }
15
+ const headerHeight = useHeaderHeight ( ) ;
16
+ const tabBarHeight = useBottomTabBarHeight ( ) ;
17
+ const [ currentPage , setCurrentPage ] = useState ( 0 ) ;
18
+
19
+ // Tanstack Query has a convenient useQuery hook that works for infinite paginating.
20
+ // This comes in handle in particular here since the GET multiple choice questions
21
+ // endpoint doesn't support pages (getting more than one per request)
22
+ const { data, error, fetchNextPage, status, isFetching, isFetchingNextPage, isLoading } =
23
+ useInfiniteQuery ( {
24
+ queryKey : [ 'questions' ] ,
25
+ queryFn : getNextQuestion ,
26
+ initialPageParam : 0 ,
27
+ getNextPageParam : ( lastPage , allPages , lastPageParam ) => {
28
+ if ( lastPage . length === 0 ) {
29
+ return undefined ;
30
+ }
31
+ return lastPageParam + 1 ;
32
+ } ,
33
+ getPreviousPageParam : ( firstPage , allPages , firstPageParam ) => {
34
+ if ( firstPageParam <= 1 ) {
35
+ return undefined ;
36
+ }
37
+ return firstPageParam - 1 ;
38
+ }
39
+ } ) ;
40
+
41
+ const currentQuestion = data ?. pages [ currentPage ] [ 0 ] ;
42
+
43
+ // Responsible for making sure we have the next 5 pages of data as the index changes
44
+ useEffect ( ( ) => {
45
+ if ( isFetching ) return ;
46
+ if ( currentPage + 5 <= ( data ?. pageParams ?. length || 0 ) ) return ;
47
+ fetchNextPage ( ) ;
48
+ } , [ currentPage , data ?. pageParams ?. length ] ) ;
49
+
50
+ const onViewableItemsChanged = useCallback (
51
+ ( {
52
+ viewableItems,
53
+ changed
54
+ } : {
55
+ viewableItems : Array < ViewToken > ;
56
+ changed : Array < ViewToken > ;
57
+ } ) => {
58
+ if ( viewableItems . length === 0 ) return ;
59
+ const { index } = viewableItems [ 0 ] ;
60
+ if ( index === null ) return ;
61
+ setCurrentPage ( index ) ;
62
+ } ,
63
+ [ ]
64
+ ) ;
65
+
66
+ console . log ( 'data' , data ?. pages . length ) ;
67
+ return (
68
+ < View className = "flex-1" >
69
+ < FlatList
70
+ data = { data ?. pages || [ ] }
71
+ renderItem = { ( { item } ) => {
72
+ return (
73
+ < Image
74
+ style = { { width : SCREEN_WIDTH , height : SCREEN_HEIGHT - tabBarHeight } }
75
+ source = { item [ 0 ] . image }
76
+ placeholder = { blurhash }
77
+ contentFit = "cover"
78
+ transition = { 1000 }
79
+ />
80
+ ) ;
81
+ } }
82
+ // Because the API is random and we are not deduping response from it. We will combine the id and index to ensure uniqueness
83
+ keyExtractor = { ( item , index ) => item [ 0 ] . id . toString ( ) + index }
84
+ snapToAlignment = "start"
85
+ snapToInterval = { SCREEN_HEIGHT - tabBarHeight }
86
+ getItemLayout = { ( data , index ) => ( {
87
+ length : SCREEN_HEIGHT - tabBarHeight ,
88
+ offset : ( SCREEN_HEIGHT - tabBarHeight ) * index ,
89
+ index
90
+ } ) }
91
+ disableIntervalMomentum
92
+ onViewableItemsChanged = { onViewableItemsChanged }
93
+ viewabilityConfig = { {
94
+ itemVisiblePercentThreshold : 50
95
+ } }
96
+ showsVerticalScrollIndicator = { false }
97
+ />
98
+
99
+ { /* <SafeAreaView style={{ marginTop: headerHeight }}></SafeAreaView> */ }
100
+ </ View >
101
+ ) ;
102
+ }
0 commit comments