We interact with many internet-based platforms in our day to day life. We use several social media platform and shopping sites. It is easy to shop through an online shopping platform. We scroll up and down to see the products or news feed. As we go down the new set of products or news feed loads automatically.
Infinite scrolling is shown in the following gif.
Without wasting time, now, I come to the point. I discussed the loading of the new set of products during scrolling the UI above. This loading of the new set of products is called pagination of the data.
Pagination:- Pagination is a sequence of pages which are connected and have similar content.
Pagination can be done in several ways. Pagination can be done with a navigation bar at the bottom or top of the page using an anchor tag with href attribute. I m not going deep into it.
This article is on the subject that how should do infinite scrolling using "Intersection Observer API" in react. How can we do pagination in the react using "Intersection Observer API"?
Before the start, I assume that you are familiar with javascript, react, react hooks and intersection observer API. If you are not familiar with intersection observer API then you should first take a look at Intersection Observer API.
Let's start now!!!.
In this article, I am using Github API for the demo of the subject. I'll fetch repos of the user and will show them on the screen.
First, I created a react app and made an InfiniteScrolling react functional component.
Now, I made repoData, totalRepos, currentPage states in the function.
function InfiniteScrolling() {
const [repoData, setRepoData] = useState([]);
const [totalRepos, setTotalRepos] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
function fetchData() {
(async () => {
const data = await fetch(`https://api.github.com/users/praveen-me/repos?
page=${totalRepos ? currentPage : 1}`).then(response => response.json());
if (currentPage < totalRepos / 30) {
setCurrentPage(currentPage + 1);
}
setRepoData([...repoData, ...data]);
})()
}
useEffect(() => {
(async () => {
const userData = await fetch("https://api.github.com/users/praveen-me")
.then(response => response.json());
setTotalRepos(userData.public_repos);
})()
fetchData();
}, [])
return (
<div className="App">
{repoData.map((repo, index) => {
return <h1 className="repo" key={repo.name + index}>{repo.name}</h1>
})}
</div>
);
}
FetchData()
function is fetching data from the given URI and setting to the states. makeRepoElem()
function is creating an array of h1
element. And a list of repo name is rendered to the page.
I have added some styling to make the good appearance of the repos.
function InfiniteScrolling() {
const [repoData, setRepoData] = useState([]);
const [totalRepos, setTotalRepos] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const callBack = useCallback((node) => {
if (node) console.log(node);
})
function fetchData() {
(async () => {
const data = await fetch(`https://api.github.com/users/praveen-me/repos?
page=${totalRepos ? currentPage : 1}`).then(response => response.json());
if (currentPage < totalRepos / 30) {
setCurrentPage(currentPage + 1);
}
setRepoData([...repoData, ...data]);
})()
}
useEffect(() => {
(async () => {
const userData = await fetch("https://api.github.com/users/praveen-me")
.then(response => response.json());
setTotalRepos(userData.public_repos);
})()
fetchData();
}, [])
return (
<div className="App">
{repoData.map((repo, index) => {
return <h1 className="repo" key={repo.name + index}>{repo.name}</h1>
})}
</div>
);
}
Now, I use a useCallback
and store a function in it. And I reference this useCallback
to the last h1
element in the map. When the last element would be created, the stored function in the useCallback
would be called.
Now, the question is where to use intersection observer API? We will follow the following steps...
1- We will create a new observer i.e. const observer = new IntersectionObserver(callback, options)
.
2- We will observe the last h1
element with this observer i.e. observer.observe(lastElement)
.
Whenever the last h1
element comes in the viewport, the callback will invoke.
function InfiniteScrolling() {
const [repoData, setRepoData] = useState([]);
const [totalRepos, setTotalRepos] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const observer = useRef();
const callBack = useCallback((node) => {
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver(argus => {
if (argus[0].isIntersecting) {
if (currentPage < totalRepos / 30) {
fetchData();
}
}
})
if (node) observer.current.observe(node);
});
function fetchData() {
(async () => {
const data = await fetch(`https://api.github.com/users/praveen-me/repos?
page=${totalRepos ? currentPage : 1}`).then(response => response.json());
if (currentPage < totalRepos / 30) {
setCurrentPage(currentPage + 1);
}
setRepoData([...repoData, ...data]);
})()
}
useEffect(() => {
(async () => {
const userData = await fetch("https://api.github.com/users/praveen-me")
.then(response => response.json());
setTotalRepos(userData.public_repos);
})()
fetchData();
}, [])
return (
<div className="App">
{repoData.map((repo, index) => {
return (index === repoData.length - 1) ? (<h1 key={repo.name + index}
className="repo" ref={callBack}>{repo.name}</h1>) : (<h1 className="repo" key={repo.name + index}>{repo.name}</h1>)
})}
</div>
);
}
Now, We need to define an observer and assign it to the useRef
hook. And in the useCallback
, we create a new intersection observer and assign it to the observer i.e. observer.current = new IntersectionObserver(callback, options)
. The callback receives a list of IntersectionObserverEntry objects and the observer. In IntersectionObserverEntry, there is a list of IntersectionObserverEntry.
We use argus[0].isIntersecting
the entry of it to check whether the target element is intersecting with the viewport or not.
Now, we observe the target element(the element on which we have to apply the observer to invoke the callback) using this observer.current
observer. We apply this observer on the last h1
element i.e. observer.current.observe(node)
which we are getting by useCallback
.
if (node) observer.current.observe(node);
Whenever the callback is invoked, we need to disconnect the observer from the last target element and need to observe again new targeted element. i.e.
if (observer.current) observer.current.disconnect();
if (node) observer.current.observe(node);
Now, whenever the last h1
element interacts with the viewport, the fetchData()
function is invoked and a list of fetched repo is set to the repoData state.
if (argus[0].isIntersecting) {
if (currentPage < totalRepos / 30) {
fetchData();
}
}
Yeee!!! We have done.
That's the way, you can use "Intersection Observer API" in react for infinite scrolling.
Top comments (1)
I'll change it.