How to Implement Infinite Scroll in React?
🎯 What Will You Learn in This Guide?
In this guide, you will implement the Infinite Scroll feature step by step in your React applications.
This feature ensures that new content is automatically loaded when the user reaches the end of the page.
You will also learn how to perform event optimization with lodash.debounce to improve scrolling performance.
As an example, we will use NASA's Astronomy Picture of the Day (APOD) API.
🧠 Technical Summary
| Criterion | Description |
|---|---|
| Main Technical Topic | Infinite Scroll mechanism in React |
| Which Problem Does It Solve? | It provides uninterrupted content flow instead of pagination. Ideal for social media-like feeds. |
| User Steps | 1️⃣ Project setup 2️⃣ Scroll event capture 3️⃣ Debounce optimization 4️⃣ API data extraction 5️⃣ Initial load and error handling |
| Technical Purpose | Automatically load data when scrolling to the bottom of the page by listening to the scroll movement |
⚙️ 1. Project Setup and Installation of Required Packages
Create the base React project to develop the infinite scroll feature.
We will use superagent for data extraction and lodash.debounce for performance optimization.
npx create-react-app genixnode-sonsuz-kaydirma
cd genixnode-sonsuz-kaydirma
npm install superagent@6.1.0 lodash.debounce@4.0.8
💡 superagent, to make API requests; lodash.debounce is used to optimize scroll events.
🧩 2. Defining the InfiniteSpace Component
Create the src/InfiniteSpace.js file and add the necessary imports.
import React, { Component } from 'react';
import request from 'superagent';
import debounce from 'lodash.debounce';
class InfiniteSpace extends Component {
constructor(props) {
super(props);
this.state = {
apods: [],
};
// Kaydırma olayını 100ms gecikmeyle debounce ediyoruz.
window.onscroll = debounce(() => {
const { loadApods } = this;
// Sayfa sonuna ulaşıldıysa yeni veriyi yükle.
if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
loadApods();
}
}, 100);
}
render() {
return (
<div style={{ padding: 10 }}>
<h1>Sonsuz Uzay!</h1>
<p>Daha fazla içerik için aşağı kaydırın!</p>
</div>
);
}
}
export default InfiniteSpace;
💬 This structure listens to the scroll event and calls the loadApods() function when scrolling to the bottom of the page.
🌠 3. Extracting Data from API and Calculating Date
a. Date Offset Calculation (dayOffset)
NASA API returns data for a single day. Let's calculate the offset to get the contents of the previous days.
dayOffset = () => {
let today = new Date();
let day = today.setDate(today.getDate() - this.state.apods.length);
return new Date(day).toISOString().split('T')[0];
};
📅 This function calculates past dates based on the number of data loaded.
b. Data Loading Method (loadApods)
Let's make a request to the API with superagent and add the incoming data to the apods array.
loadApods = () => {
this.setState({ isLoading: true }, () => {
request
.get('https://api.nasa.gov/planetary/apod?date=' + this.dayOffset() + '&api_key=DEMO_KEY')
.then((results) => {
const nextApod = {
date: results.body.date,
title: results.body.title,
explanation: results.body.explanation,
copyright: results.body.copyright,
media_type: results.body.media_type,
url: results.body.url,
};
this.setState(prevState => ({
hasMore: prevState.apods.length < 5,
isLoading: false,
apods: [...prevState.apods, nextApod],
}));
})
.catch((err) => {
this.setState({ error: err.message, isLoading: false });
});
});
};
🚀 This function pulls a new day's data with each scroll and adds it to the list.
🪐 4. Initial Loading and Status Management
Let's pull the first data when the component is loaded. Let's also manage error, isLoading and hasMore states.
componentDidMount() {
this.loadApods();
}
this.state = {
error: false,
hasMore: true,
isLoading: false,
apods: [],
};
// Scroll sırasında duruma göre işlem yap
window.onscroll = debounce(() => {
const { loadApods, state: { error, isLoading, hasMore } } = this;
if (error || isLoading || !hasMore) return;
if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
loadApods();
}
}, 100);
⚙️ isLoading blocks repetitive requests, catches error errors, and hasMore determines the content limit.
🌌 5. Rendering the Data
Let's list the data from the API on the screen.
render() {
const { error, hasMore, isLoading, apods } = this.state;
return (
<div style={{ padding: 10 }}>
<h1>Sonsuz Uzay Galerisi</h1>
<p>Daha fazla içerik için aşağı kaydırın!</p>
{apods.map(apod => (
<React.Fragment key={apod.date}>
<hr />
<div>
<h2>{apod.title}</h2>
{apod.media_type === 'image' &&
<img src={apod.url} alt={apod.title} style={{ maxWidth: '100%', height: 'auto' }} />
}
{apod.media_type === 'video' &&
<iframe src={apod.url} width='640' height='360' style={{ maxWidth: '100%' }}></iframe>
}
<p>{apod.explanation}</p>
<small>Telif Hakkı: {apod.copyright}</small>
</div>
</React.Fragment>
))}
<hr />
{error && <div style={{ color: '#900' }}>Hata: {error}</div>}
{isLoading && <div>Yeni içerikler yükleniyor...</div>}
{!hasMore && <div>Tüm içerik yüklendi.</div>}
</div>
);
}
💡 Images and videos are rendered dynamically, and status information is shown to the user.
🚀 6. Include in App.js File
import React from 'react';
import InfiniteSpace from './InfiniteSpace';
function App() {
return (
<div className="App">
<InfiniteSpace />
</div>
);
}
export default App;
🔭 Now run the npm start command. As you scroll down the page in the browser, you will see new NASA content loading automatically.
💬 Frequently Asked Questions (FAQ)
- Does infinite scrolling cause performance issues?
Yes, browser memory can become bloated if not implemented correctly. Using debounce preserves performance by reducing event frequency.
- Can throttle be used instead of debounce?
Yes. debounce waits until events stop; Throttle, on the other hand, works at certain intervals. Debounce is generally more appropriate in infinite scrolling.
- What does hasMore do?
When there is no new data, hasMore = false and requests stop. This maintains API limits and prevents unnecessary installations.
- Is the Intersection Observer API available?
Absolutely yes. It is a modern method and a target element to be observed is determined instead of the scroll. It improves mobile performance and is the recommended approach.
- Why do we use componentDidMount in the beginning?
At least one piece of content must be displayed when the page first loads. This method automatically makes the first API call.
🏁 Result
In this guide, you learned how to implement Infinite Scroll feature in React. You provided uninterrupted content flow to the user with scroll detection, debounce optimization and error management.
💡 Now try this feature in your React projects on GenixNode and provide a smooth experience to your users!
yaml

