Introduction
Infinite Scrolling is a feature that allows you to load more data when the user scrolls to the bottom of the list. It is a great way to add more content to your app without having to make additional API calls.
Benefit of this technique is that we don’t all of our data at once , we only get our data when the user needs it this will allow our app to have faster load time which is very essential for our App.
In this tutorial I have assumed that you have already installed the React Native CLI or Expo and have installed and set up Laravel and its dependencies. You have a table in your database which has the data of your app and you have a Route which is responsible for fetching the data from the database.
Let’s Get Started
Laravel Backend
Let’s start with our API. As you see I have a table called article which has some articles stored in it. Bellow is the route that is responsible for fetching the data from the database.
Route::get("/get-articles",[ArticlesController::class,'getArticlesApi']);
Now we have our API route which is responsible for fetching the data. In our ArticlesController.php
we have a method called getArticlesApi
which is as bellow.
<?php
namespace App\Http\Controllers;
use App\Models\Article;
use Illuminate\Http\Request;
class ArticlesController extends Controller
{
...
...
public function getArticlesApi()
{
$articles = Article::orderBy('created_at', 'DESC')
->with("website:id,title")
->paginate(6);
return response()->json(['status' => 1, 'articles' => $articles]);
}
...
...
}
To Explain the above code.
- The
orderBy('created_at', 'DESC')
is used to sort the data in descending order to get the latest articles first. - The
with("website:id,title")
is used to get the website title of the article from a separate table using eager loading which is a feature of Eloquent. - The **
paginate(6**)
is used to get the data in chunks of 6.
The paginate(6)
is very important because we are using the infinite scrolling feature and we don’t want to load all the data at once. The paginate method will provide us with the data in chunks of 6 and also links to get the rest of our data when we scroll to the bottom of the list.
Now we have our API route which is responsible for fetching the data. In our ArticlesController.php
we have a method called getArticlesApi()
to get the data.
If you have done everything correctly then you should see the data in the response. The data will be something like this:
{
"status": 1,
"articles": {
"current_page": 1,
"data": [
{
"id": 150,
"title": "First Mover Asia: Bitcoin Falls in Pre-Holiday Trading;",
"excerpt": "A recovery in the Tether-Chinese yuan pairing",
"image": "",
"category_id": 1,
"website_id": 2,
"created_at": "2021-11-25T04:05:16.000000Z",
"updated_at": "2021-11-25T04:06:00.000000Z",
"slug": "first-mover-asia-bitcoin-falls-in-pre-holiday-trading-ether-drops",
"website": { "id": 2, "title": "Yahoo Finance" }
},
{
"id": 151,
"title": "US regulators aim for greater legal ",
"excerpt": "US banking regulators have shared their .",
"image": "",
"category_id": 1,
"website_id": 2,
"created_at": "2021-11-25T04:05:16.000000Z",
"updated_at": "2021-11-25T04:05:16.000000Z",
"slug": "us-regulators-aim-for-greater-legal-",
"website": { "id": 2, "title": "Yahoo Finance" }
},
.....
],
"first_page_url": "https://localhost:8000/api/get-articles?page=1",
"from": 1,
"last_page": 20,
"last_page_url": "https://localhost:8000/api/get-articles?page=20",
"links": [
{ "url": null, "label": "« Previous", "active": false },
{
"url": "https://localhost:8000/api/get-articles?page=1",
"label": "1",
"active": true
},
{
"url": "https://localhost:8000/api/get-articles?page=2",
"label": "2",
"active": false
}
],
"next_page_url": "https://localhost:8000/api/get-articles?page=2",
"path": "https://localhost:8000/api/get-articles",
"per_page": 6,
"prev_page_url": null,
"to": 6,
"total": 119
}
}
To analyze the response,
- We can use the
response.data
property to access the data. - The Important thing that we need here is
next_page_url
using this link we can get the next page of data and we will get the same response with 6 new articles in the response and if the data is remaining then we will get a newnext_page_url
.
Since our backend is fully functional and we have the data we can now start to build the frontend and move to React Native.
Frontend React Native
For React Native, I have assumed the you have a working project and installed all the dependencies including axios
which is used to make the API calls.
In our React Native we will have function to get data from the API which will be something like this:
const [news, setNews] = useState(null);
const [nextPageUrl, setNextPageUrl] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
getData();
}, []);
const getData = () => {
API.get("https://localhost:8000/api/get-articles")
.then((res) => {
setNews(res.data.articles.data);
setNextPageUrl(res.data.articles.next_page_url);
if (isLoading) setIsLoading(false);
}).catch((err) => {
// console.log(err.message);
setErrMsg(err.message);
if (isLoading) setIsLoading(false);
});
};
When we get the data in then()
we will set the state of news
and nextPageUrl
.
The news
is our 6 articles which we got from the API and the nextPageUrl
is the link to the next page of data.
The isLoading
is a Boolean which we will use to show the loading spinner.
To display the data we will use the FlatList component which is a list of items.
I won’t bore you with the details of how to use the FlatList component. Since if your are looking for infinite scrolling, you can use the FlatList component.
The part of the Flatlist that we are interested in is the onEndReached
and onEndReachedThreshold
property of the Flatlist.
onEndReached
gets a function which will be called when the user scrolls to the end of the list or scroll past the onEndReachedThreshold
property.
onEndReachedThreshold
is a number between 0 and 1 which is the fraction of the list that has been scrolled before onEndReached
is called.
...
return (
<FlatList
onEndReached={getNextPageData}
onEndReachedThreshold={0.5}
...
>
);
...
The onEndReached
will call the getNextPageData()
function when the user scrolls to the end of the list.
The getNextPageData
function will be something like this:
const [loadingMore, setLoadingMore] = useState(false);
const getNextPageData = () => {
// we check if the nextPageUrl state is not null
if (nextPageUrl != null) {
// is a flag to show or hide the loading spinner at the bottom of the list
setLoadingMore(true);
axios.get(nextPageUrl)
.then((res) => {
setNews([...news, ...res.data.articles.data]);
setNextPageUrl(res.data.articles.next_page_url);
// we use the if(loadingMore) to avoid unnecessary setting of the state.
// this will assure that we only change state when it necessary
if(loadingMore) setLoadingMore(false);
})
.catch((err) => {
setLoadingMore(false);
setErrMsg(err);
});
} else {
setErrMsg("No more data");
}
};
The getNextPageData
function will call the axios.get
function to get the next page of data.
but first we check that the existing nextPageUrl
is not null because if is it null then we don’t have any other data to get and we wont call the API.
If our request is successful we will get 6 new articles and a new nextPageUrl
from the API which we need store in the state.
Since we don’t want to lose our previous data we will use the spread operator like bellow:
setNews([...news, ...res.data.articles.data]);
To add the new data to the existing data. The new data will be appended at the bottom of the list which is what we want.
We will also set the loadingMore
flag to false to hide the loading spinner. and finally we set the nextPageUrl
to the new value which we got from the API.
in here if there is no more data left in the database the nextPageUrl
will be null, this is helping because at the beginning of this function we checked for the nextPageUrl
to not be null.
To summarize what we have done in React Native is:
- Get the data from the API
- Get the
next_page_url
and store it in a State Variable - Define the
getNextPageData
function - Set
onEndReached
andonEndReachedThreshold
for the FlatList
import React ,{useState,useEffect} from "react";
import {
ActivityIndicator,
FlatList,
Image,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
import SkeletonContent from "react-native-skeleton-content";
import axios from "axios";
const News = ({ isDarkTheme }) => {
const [news, setNews] = useState(null);
const [nextPageUrl, setNextPageUrl] = useState(null);
const [loadingMore, setLoadingMore] = useState(false);
const [errMsg, setErrMsg] = useState("");
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// 1- Get the data from the API
getData();
}, []);
const getData = () => {
API.get("https://localhost:8000/api/get-articles")
.then((res) => {
setNews(res.data.articles.data);
// 2- Get the next_page_url and store it in a State Variable
setNextPageUrl(res.data.articles.next_page_url);
if (refreshing) setRefreshing(false);
if (isLoading) setIsLoading(false);
})
.catch((err) => {
// console.log(err.message);
setErrMsg(err.message);
if (refreshing) setRefreshing(false);
if (isLoading) setIsLoading(false);
});
};
// 4- define the getNextPageData function
const getNextPageData = () => {
// we check if the nextPageUrl state is not null
if (nextPageUrl != null) {
// is a flag to show or hide the loading spinner at the bottom of the list
setLoadingMore(true);
axios.get(nextPageUrl)
.then((res) => {
setNews([...news, ...res.data.articles.data]);
setNextPageUrl(res.data.articles.next_page_url);
// we use the if(loadingMore) to avoid unnecessary setting of the state.
// this will assure that we only change state when it necessary
if(loadingMore) setLoadingMore(false);
})
.catch((err) => {
setLoadingMore(false);
setErrMsg(err);
});
} else {
setErrMsg("No more data");
}
};
if(isLoading) {
return (
...
)
}
// 3- set onEndReached and onEndReachedThreshold for the FlatList
return (
<FlatList
onEndReached={getNextPageData}
onEndReachedThreshold={0.5}
data={news}
keyExtractor={(item) => `${item.id}`}
renderItem={({ item }) => {
return (
...
);
}}
/>
);
}
That was all about infinite scrolling in React Native and Laravel to get you started with the topic. Obviously you can use the same code in React Native or React JS. You can do a lot more with the data taken from the API and implement it in your project or add new features to it.
I hope this has helped you to understand how to use the API in your project. thanks for reading. Don’t forget to share this article with your friends.
See it in actions: