{"id":20008563,"url":"https://github.com/iamnilotpal/infinite-scroll","last_synced_at":"2025-06-16T04:38:28.858Z","repository":{"id":179827147,"uuid":"553376015","full_name":"iamNilotpal/infinite-scroll","owner":"iamNilotpal","description":"Infinite scrolling using FlashList and React Query","archived":false,"fork":false,"pushed_at":"2022-10-30T14:54:04.000Z","size":13942,"stargazers_count":32,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-16T04:38:26.242Z","etag":null,"topics":["flash-list","infinite-scroll","react-native","react-query"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iamNilotpal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-10-18T05:51:07.000Z","updated_at":"2025-04-09T19:06:05.000Z","dependencies_parsed_at":null,"dependency_job_id":"7d502963-c124-48ee-a961-e7ce22d30f14","html_url":"https://github.com/iamNilotpal/infinite-scroll","commit_stats":null,"previous_names":["iamnilotpal/infinite-scroll"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/iamNilotpal/infinite-scroll","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamNilotpal%2Finfinite-scroll","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamNilotpal%2Finfinite-scroll/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamNilotpal%2Finfinite-scroll/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamNilotpal%2Finfinite-scroll/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iamNilotpal","download_url":"https://codeload.github.com/iamNilotpal/infinite-scroll/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamNilotpal%2Finfinite-scroll/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260097336,"owners_count":22958185,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flash-list","infinite-scroll","react-native","react-query"],"created_at":"2024-11-13T07:10:39.529Z","updated_at":"2025-06-16T04:38:28.838Z","avatar_url":"https://github.com/iamNilotpal.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"## The Problem\n\nSince I first began using React Native, I have encountered this warning at least a dozen times, or maybe you too:\n\n```bash\nVirtualizedList: You have a large list that is slow to update — make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, React.memo, useCallback, useMemo etc.\n```\n\nRight, it seems familiar isn't it? This typically occurs when we load up a FlatList with lots of items that aren't just static text or images but instead have components with animations or data from third party api or other interactions.\n\n## Why FlashList?\n\nThe listing interface used by `FlatList`, which is based on ScrollView, is termed VirtualizedList. Under the hood, VirtualizedList makes use of a rendering API that renders an enumerable list of items as a scroll. Perhaps because we use the newest iPhone and effortlessly post to Instagram every day, we don't see it. Even if everything appears to be in order, you can still encounter this problem if your project runs on low-end devices, particularly Android ones. Simply put, in order to figure it out, such strategies also require some computations.\n\nHere comes to rescue `FlashList`, An alternative to FlatList that uses the UI thread and, according to their website, is 10 times quicker in JS and 5 times faster in JS thread. These performance gains are pretty impressive, even if only half the improvement is taken into account.\n\n## Initializing React Native App\n\nWe will use **React Native CLI** to create our app. Make sure to check out their [installation guide](https://reactnative.dev/docs/environment-setup) if you haven't. I will be using TypeScript in this project.\n\nTo get started run this command :\n\n```bash\nnpx react-native init InfiniteScroll --template react-native-template-typescript\n```\n\nNow wait until the installation is finished and then navigate to that directory.\n\n```bash\ncd InfiniteScroll\n```\n\n## Installing Dependencies\n\nWe will be using `React Navigation` in the project.Install the dependencies by running the command below. Here i'm using yarn you can use npm too.\n\n```bash\nyarn add @shopify/flash-list react-query @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/native-stack\n```\n\n## Setting up React Query\n\nIn order to use react-query in our project we need to setup some things. So, open you App.tsx file and add the following code.\n\n```js\nimport React from 'react';\nimport { StatusBar, StyleSheet, View } from 'react-native';\nimport { QueryClient, QueryClientProvider } from 'react-query';\n\nconst queryClient = new QueryClient();\n\nconst App = () =\u003e {\n  return (\n    \u003cQueryClientProvider client={queryClient}\u003e\n      \u003cStatusBar barStyle=\"light-content\" backgroundColor=\"#201d29\" /\u003e\n      \u003cView style={styles.container}\u003e\n        \u003cText\u003eHello, World\u003c/Text\u003e\n      \u003c/View\u003e\n    \u003c/QueryClientProvider\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    width: '100%',\n    height: '100%',\n    backgroundColor: '#201d29',\n  },\n});\n\nexport default App;\n```\n\n\u003e Note: I wont be covering the styling part. You can add your own styles or copy mine.\n\n## Creating Components\n\nNow before moving ahead let's setup React Navigation. First create a folder `src` in the root of the project. Then create two new folders `navigation` and `screens` in `src`. In the navigation folder add two files `AppNavigation.tsx` and `RootNavigation.tsx`. `RootNavigation.tsx` will contain the NavigationContainer and the Stack Navigator exported from `AppNavigation.tsx`. Now add 2 files in the `screens` folder, `Cats.tsx` and `Cat.tsx` and export a default component from each file. Now add the following code in both `AppNavigation.tsx` and `RootNavigation.tsx`.\n\nIn `AppNavigation.tsx` :\n\n```js\nimport { createNativeStackNavigator } from '@react-navigation/native-stack';\nimport React from 'react';\nimport { CatType } from '../components/Cats/types';\n\nimport CatScreen from '../screens/Cat';\nimport CatsScreen from '../screens/Cats';\nimport HomeScreen from '../screens/Home';\n\nexport type AppStackParams = {\n  HomeScreen: undefined;\n  CatsScreen: undefined;\n  CatScreen: CatType;\n};\n\nconst AppStack = createNativeStackNavigator\u003cAppStackParams\u003e();\n\nconst AppNavigation = () =\u003e {\n  return (\n    \u003cAppStack.Navigator\n      screenOptions={{ headerShown: false, animation: 'slide_from_right' }}\u003e\n      \u003cAppStack.Screen name=\"HomeScreen\" component={HomeScreen} /\u003e\n      \u003cAppStack.Screen name=\"CatsScreen\" component={CatsScreen} /\u003e\n      \u003cAppStack.Screen name=\"CatScreen\" component={CatScreen} /\u003e\n    \u003c/AppStack.Navigator\u003e\n  );\n};\n\nexport default AppNavigation;\n```\n\nIn `RootNavigation.tsx` :\n\n```js\nimport { DefaultTheme, NavigationContainer } from '@react-navigation/native';\nimport React from 'react';\nimport AppNavigation from './AppNavigation';\n\nconst theme = Object.freeze({\n  ...DefaultTheme,\n  colors: {\n    ...DefaultTheme.colors,\n    background: '#201d29',\n  },\n});\n\nconst RootNavigation = () =\u003e {\n  return (\n    \u003cNavigationContainer theme={theme}\u003e\n      \u003cAppNavigation /\u003e\n    \u003c/NavigationContainer\u003e\n  );\n};\n\nexport default RootNavigation;\n```\n\nUpdate the `App.tsx` file with the following code :\n\n```js\nimport React from 'react';\nimport { StatusBar, View } from 'react-native';\nimport { QueryClient, QueryClientProvider } from 'react-query';\nimport RootNavigation from './src/navigation/RootNavigation';\n\nconst queryClient = new QueryClient();\n\nconst App = () =\u003e {\n  return (\n    \u003cQueryClientProvider client={queryClient}\u003e\n      \u003cStatusBar barStyle=\"light-content\" backgroundColor=\"#201d29\" /\u003e\n      \u003cView style={styles.container}\u003e\n        \u003cRootNavigation /\u003e\n      \u003c/View\u003e\n    \u003c/QueryClientProvider\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    width: '100%',\n    height: '100%',\n    backgroundColor: '#201d29',\n  },\n});\n\nexport default App;\n```\n\n## Creating Components\n\nNavigation looks okay so to get started let's first create some components. First create a directory called `src` in your root folder. Inside `src` create two new folders `components` and `hooks`. Now create a folder `Cats` inside `components` and inside that create `index.jsx` and `CatCard.jsx` file.\n\nIn `CatCard.tsx` add the following code :\n\n```js\nimport React from 'react';\nimport { useNavigation } from '@react-navigation/native';\nimport { NativeStackNavigationProp } from '@react-navigation/native-stack';\nimport { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';\n\nimport { AppStackParams } from '../../../navigation/AppNavigation';\nimport { CatType } from '../types';\n\nconst CatCard: React.FC\u003c{ item: CatType; index: number }\u003e = ({\n  item,\n  index,\n}) =\u003e {\n  const { image, name, origin } = item;\n  const navigation = useNavigation\u003cNativeStackNavigationProp\u003cAppStackParams\u003e\u003e();\n\n  return (\n    \u003cView\u003e\n      \u003cTouchableOpacity\n        style={styles.container}\n        activeOpacity={0.8}\n        onPress={() =\u003e navigation.navigate('CatScreen', item)}\u003e\n        \u003cImage\n          source={{ uri: image.url }}\n          resizeMode=\"center\"\n          style={styles.image}\n        /\u003e\n        \u003cText style={styles.name}\u003e{name}\u003c/Text\u003e\n        \u003cText style={styles.origin}\u003e{origin}\u003c/Text\u003e\n      \u003c/TouchableOpacity\u003e\n    \u003c/View\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    width: 170,\n    padding: 12,\n    borderRadius: 10,\n    marginBottom: 20,\n    backgroundColor: '#403c4a',\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  image: {\n    width: 70,\n    height: 70,\n    borderRadius: 80,\n  },\n  name: {\n    color: '#f4f2fb',\n    fontSize: 16,\n    fontWeight: 'bold',\n    marginTop: 10,\n  },\n  origin: {\n    color: '#b1acb9',\n    fontSize: 12,\n    fontWeight: '600',\n    marginBottom: 5,\n  },\n});\n\nexport default CatCard;\n```\n\nDon't worry about the `index` prop. We will be using it later.\n\nHere we're importing `CatTpe` from `types` folder. So add a types folder and a `index.ts` file and add the following code :\n\n```js\nexport type CatType = {\n  id: string,\n  name: string,\n  origin: string,\n  description: string,\n  life_span: string,\n  temperament: string,\n  adaptability: number,\n  child_friendly: number,\n  stranger_friendly: number,\n  wikipedia_url: string,\n  image: {\n    width: number,\n    height: number,\n    id: string,\n    url: string,\n  },\n};\n```\n\nIn `index.tsx` file put the following code :\n\n```js\nimport { FlashList } from '@shopify/flash-list';\nimport React from 'react';\n\nimport CatCard from './CatCard';\nimport { CatType } from './types';\n\ntype CatsPreviewProps = {\n  catsData: any[] | undefined | CatType[],\n  loadMoreCats: () =\u003e void,\n  isFetching: boolean,\n};\n\nconst CatsPreview: React.FC\u003cCatsPreviewProps\u003e = ({\n  catsData,\n  loadMoreCats,\n  isFetching,\n}) =\u003e {\n  return (\n    \u003cFlashList\n      data={catsData}\n      renderItem={({ item, index }: { item: CatType, index: number }) =\u003e (\n        \u003cCatCard item={item} key={item.id} index={index} /\u003e\n      )}\n      keyExtractor={item =\u003e item.id}\n      numColumns={2}\n      estimatedItemSize={190 * 15}\n      refreshing={isFetching}\n      onRefresh={loadMoreCats}\n      onEndReached={loadMoreCats}\n      onEndReachedThreshold={0.1}\n      contentContainerStyle={{ paddingVertical: 12 }}\n    /\u003e\n  );\n};\n\nexport default CatsPreview;\n```\n\nIn the above code we're accepting `catsData`, `loadMoreCats` and `isFetching` as props. To break it down `catsData` is the data that will be shown in the screen. When scroll position reaches the threshold value, a function to load new data can be called. In React Native, the threshold value ranges from 0 to 1, with 0.5 serving as the default. In above code we have used the function `loadMoreCats` which will be used to fetch cats when scrolling. FlashList provides `RefreshControl` which can be used show to a loading indicator while fetching data. To use it we need to provide two props to `FlashList`, `refreshing` and `onRefresh`. `refreshing` is boolean property and `onRefresh` is a callback function which will be called while fetching. For `refreshing` we got `isFetching` and for `onRefresh` we have `loadMoreCats`.\n\n## Fetching Data\n\nTo fetch data we will utilize a custom hook. To get started create a file `useCats.ts` inside `hooks` directory. We will be fetching data from the [Cats API](https://thecatapi.com) and will use the `useInfiniteQuery` hook from react-query. `useInfiniteQuery` hooks accepts the same arguments as `useQuery`. First one is an array of unique keys, second is a fetcher function which will fetch the data and third is an optional object with some properties.\n\nInside `useCats.ts` file add the following code :\n\n```js\nimport { useInfiniteQuery } from 'react-query';\n\nconst fetcher = async (pageNumber: number = 0) =\u003e {\n  try {\n    const response = await fetch(\n      `https://api.thecatapi.com/v1/breeds?limit=20\u0026page=${pageNumber}`,\n    );\n    const data = await response.json();\n    return { data, nextPage: pageNumber + 1 };\n  } catch (error) {\n    if (error instanceof Error) throw new Error(error.message);\n    else throw new Error('Something went wrong.');\n  }\n};\n\nexport default function useCats() {\n  const {\n    data,\n    isError,\n    isLoading,\n    error,\n    isFetching,\n    hasNextPage,\n    fetchNextPage,\n  } = useInfiniteQuery(['dogs'], () =\u003e fetcher(), {\n    getNextPageParam: ({ nextPage }) =\u003e nextPage,\n    staleTime: Infinity,\n  });\n\n  return {\n    data,\n    isError,\n    isLoading,\n    error,\n    isFetching,\n    hasNextPage,\n    fetchNextPage,\n  };\n}\n```\n\nIn the above code the `fetcher` function accepts an argument `pageNumber` to paginate the data form the api. The returned data is also modified, which is an object containing the keys data and nextPage. Every time an API call is successful, nextPage is increased. This format of the data is required by useInfiniteQuery. The response we received from the `fetcher` method is passed as the lastPage parameter, which is accepted by getNextPageParam, which then returns the subsequent page. `useInfiniteQuery` returns several additional methods to us. There are now functions `fetchNextPage` and a boolean property `hasNextPage` which indicates if we can make more query.\n\n## Combining everything\n\nThe data format returned by `useInfiniteQuery` is an object with two keys:\n\n- pageParams - an array of the page number\n- pages - an array of our data for each page\n\nIn order to map through the data for each page as an array and render them, we must flatten the pages first. We can use the flatMap method.\n\n```js\nconst catsData = data?.pages.flatMap(page =\u003e page.data);\n```\n\nOpen the `Cats.tsx` file inside `screens` folder and add the following code :\n\n```js\nimport React from 'react';\nimport { StyleSheet, Text, View } from 'react-native';\n\nimport CatsPreview from '../../components/Cats';\nimport useCats from '../../hooks/useCats';\n\nconst CatsScreen = () =\u003e {\n  const { isError, data, error, fetchNextPage, hasNextPage, isFetching } =\n    useCats();\n\n  const catsData = data?.pages.flatMap(page =\u003e page.data);\n  const loadMoreCats = () =\u003e hasNextPage \u0026\u0026 fetchNextPage();\n\n  return (\n    \u003cView style={styles.container}\u003e\n      {isError \u0026\u0026 (\n        \u003cText style={styles.error}\u003e\n          {error instanceof Error ? error.message : 'Something went wrong'}.\n        \u003c/Text\u003e\n      )}\n      \u003cCatsPreview\n        catsData={catsData}\n        isFetching={isFetching}\n        loadMoreCats={loadMoreCats}\n      /\u003e\n    \u003c/View\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    height: '100%',\n    width: '100%',\n    marginLeft: 12,\n  },\n  error: {\n    color: '#ffe742',\n    fontSize: 18,\n    fontWeight: '600',\n    textAlign: 'center',\n    marginVertical: 20,\n  },\n});\n\nexport default CatsScreen;\n```\n\n**After everything our app should look something like this :**\n\n\u003cimg src=\"./src/assets/screenshot-1.jpg\" height=\"300\"/\u003e\n\nIt's kind of good but when the app first loads we get a non pleasant layout shift. To fix this lets first add a npm package `react-native-animatable` :\n\n```bash\nyarn add react-native-animatable\n```\n\nNow open the `CatCard.tsx` file and update with the following code :\n\n```js\nimport React from 'react';\nimport { useNavigation } from '@react-navigation/native';\nimport { View as AnimatedView } from 'react-native-animatable';\nimport { Image, StyleSheet, Text, TouchableOpacity } from 'react-native';\nimport { NativeStackNavigationProp } from '@react-navigation/native-stack';\n\nimport { AppStackParams } from '../../../navigation/AppNavigation';\nimport { CatType } from '../types';\n\nconst CatCard: React.FC\u003c{ item: CatType; index: number }\u003e = ({\n  item,\n  index,\n}) =\u003e {\n  const { image, name, origin } = item;\n  const navigation = useNavigation\u003cNativeStackNavigationProp\u003cAppStackParams\u003e\u003e();\n\n  return (\n    \u003cAnimatedView animation=\"slideInUp\" duration={500} delay={index}\u003e\n      \u003cTouchableOpacity\n        style={styles.container}\n        activeOpacity={0.8}\n        onPress={() =\u003e navigation.navigate('CatScreen', item)}\u003e\n        \u003cImage\n          source={{ uri: image.url }}\n          resizeMode=\"center\"\n          style={styles.image}\n        /\u003e\n        \u003cText style={styles.name}\u003e{name}\u003c/Text\u003e\n        \u003cText style={styles.origin}\u003e{origin}\u003c/Text\u003e\n      \u003c/TouchableOpacity\u003e\n    \u003c/AnimatedView\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  container: {\n    width: 170,\n    padding: 12,\n    borderRadius: 10,\n    marginBottom: 20,\n    backgroundColor: '#403c4a',\n    alignItems: 'center',\n    justifyContent: 'center',\n  },\n  image: {\n    width: 70,\n    height: 70,\n    borderRadius: 80,\n  },\n  name: {\n    color: '#f4f2fb',\n    fontSize: 16,\n    fontWeight: 'bold',\n    marginTop: 10,\n  },\n  origin: {\n    color: '#b1acb9',\n    fontSize: 12,\n    fontWeight: '600',\n    marginBottom: 5,\n  },\n});\n\nexport default CatCard;\n```\n\nHere I'm using `slideInUp` animation. Use can use other animation types. I'm using the index number to delay the animation of each card.\n\nNow let's add the screen to view each Cat's detailed information. We've an `onPress` handler on the **CatCard** and passing the cat data to the **CatScreen** page. Update the `Cat.tsx` file :\n\n```js\nimport { RouteProp, useNavigation, useRoute } from '@react-navigation/native';\nimport { NativeStackNavigationProp } from '@react-navigation/native-stack';\nimport React from 'react';\nimport {\n  Image,\n  ImageSourcePropType,\n  Linking,\n  ScrollView,\n  StyleSheet,\n  Text,\n  TouchableOpacity,\n  View,\n} from 'react-native';\n\nimport arrowLeft from '../../assets/arrow-left.png';\nimport { AppStackParams } from '../../navigation/AppNavigation';\nimport styles from './styles';\n\nconst CatScreen = () =\u003e {\n  const { params: cat } = useRoute\u003cRouteProp\u003cAppStackParams, 'CatScreen'\u003e\u003e();\n  const navigation = useNavigation\u003cNativeStackNavigationProp\u003cAppStackParams\u003e\u003e();\n\n  return (\n    \u003cScrollView\u003e\n      \u003cImage\n        source={{ uri: cat.image.url }}\n        style={styles.image}\n        resizeMode=\"cover\"\n      /\u003e\n      \u003cTouchableOpacity\n        style={styles.arrowContainer}\n        onPress={() =\u003e navigation.goBack()}\u003e\n        \u003cImage source={arrowLeft as ImageSourcePropType} style={styles.arrow} /\u003e\n      \u003c/TouchableOpacity\u003e\n      \u003cView style={styles.textContainer}\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.name}\u003e{cat.name}\u003c/Text\u003e\n          \u003cText style={styles.origin}\u003e{cat.origin}\u003c/Text\u003e\n        \u003c/View\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.heading}\u003eDescription\u003c/Text\u003e\n          \u003cText style={styles.text}\u003e{cat.description}\u003c/Text\u003e\n        \u003c/View\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.heading}\u003eTemperament\u003c/Text\u003e\n          \u003cText style={styles.text}\u003e{cat.temperament}\u003c/Text\u003e\n        \u003c/View\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.heading}\u003eLife span\u003c/Text\u003e\n          \u003cText style={styles.text}\u003e{cat.life_span} years\u003c/Text\u003e\n        \u003c/View\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.heading}\u003eScores\u003c/Text\u003e\n          \u003cView style={styles.flex}\u003e\n            \u003cText style={styles.text}\u003eAdaptability\u003c/Text\u003e\n            \u003cText style={styles.mr}\u003e-\u003c/Text\u003e\n            \u003cText style={styles.text}\u003e{cat.adaptability}\u003c/Text\u003e\n          \u003c/View\u003e\n          \u003cView style={styles.flex}\u003e\n            \u003cText style={styles.text}\u003eChild Friendly\u003c/Text\u003e\n            \u003cText style={styles.mr}\u003e-\u003c/Text\u003e\n            \u003cText style={styles.text}\u003e{cat.child_friendly}\u003c/Text\u003e\n          \u003c/View\u003e\n          \u003cView style={styles.flex}\u003e\n            \u003cText style={styles.text}\u003eStranger Friendly\u003c/Text\u003e\n            \u003cText style={styles.mr}\u003e-\u003c/Text\u003e\n            \u003cText style={styles.text}\u003e{cat.stranger_friendly}\u003c/Text\u003e\n          \u003c/View\u003e\n        \u003c/View\u003e\n        \u003cView style={styles.container}\u003e\n          \u003cText style={styles.heading}\u003eWikipedia URL\u003c/Text\u003e\n          \u003cText\n            style={[styles.text, { color: '#2d7fea' }]}\n            onPress={() =\u003e Linking.openURL(cat.wikipedia_url)}\u003e\n            {cat.wikipedia_url}\n          \u003c/Text\u003e\n        \u003c/View\u003e\n      \u003c/View\u003e\n    \u003c/ScrollView\u003e\n  );\n};\n\nconst styles = StyleSheet.create({\n  image: { width: '100%', height: 300 },\n  arrowContainer: {\n    position: 'absolute',\n    width: 27,\n    height: 27,\n    padding: 7,\n    backgroundColor: '#f4f73e',\n    borderRadius: 50,\n    top: 15,\n    left: 15,\n  },\n  arrow: {\n    width: '100%',\n    height: '100%',\n  },\n  textContainer: { paddingBottom: 15, paddingHorizontal: 20 },\n  name: {\n    color: '#f5f2fc',\n    fontSize: 35,\n    fontWeight: '700',\n    marginBottom: -2,\n  },\n  origin: { color: '#767980', fontSize: 20, fontWeight: '700' },\n  container: {\n    marginTop: 20,\n  },\n  heading: {\n    fontWeight: '700',\n    fontSize: 15,\n    color: '#d4d0e0',\n    marginBottom: 5,\n  },\n  text: { fontWeight: '500', fontSize: 13, color: '#767980' },\n  flex: { flexDirection: 'row', alignItems: 'center' },\n  mr: { marginHorizontal: 10 },\n});\n\nexport default CatScreen;\n```\n\n**If everything was okay it should look something like this :**\n\n\u003cimg src=\"./src/assets/screenshot-2.jpg\" height=\"300\" /\u003e\n\n## Conclusion\n\nThis concludes our app. I believe React Query and FlashList is more capable and will become more well-liked by the community, I believe, other developers to can give it a shot.\n\nRepo link [React Query Infinite Scroll](https://github.com/iamNilotpal/infinite-scroll)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamnilotpal%2Finfinite-scroll","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiamnilotpal%2Finfinite-scroll","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamnilotpal%2Finfinite-scroll/lists"}