{"id":7603,"date":"2025-07-06T07:32:24","date_gmt":"2025-07-06T07:32:23","guid":{"rendered":"https:\/\/namastedev.com\/blog\/?p=7603"},"modified":"2025-07-06T07:32:24","modified_gmt":"2025-07-06T07:32:23","slug":"implementing-infinite-scroll-in-react-2","status":"publish","type":"post","link":"https:\/\/namastedev.com\/blog\/implementing-infinite-scroll-in-react-2\/","title":{"rendered":"Implementing Infinite Scroll in React"},"content":{"rendered":"<h1>Implementing Infinite Scroll in React<\/h1>\n<p>Infinite scrolling is a user interface pattern that allows users to load more content as they scroll down a page. This technique is particularly useful for applications displaying large sets of data, such as photo galleries or list views, providing a seamless experience without the need for pagination. In this article, we&#8217;ll explore how to implement infinite scroll in a React application.<\/p>\n<h2>Why Use Infinite Scroll?<\/h2>\n<p>Infinite scroll enhances user experience by:<\/p>\n<ul>\n<li><strong>Reducing Load Time:<\/strong> Users can access more content without loading a new page.<\/li>\n<li><strong>Engagement:<\/strong> It creates a continuous flow of content, keeping users engaged for a longer time.<\/li>\n<li><strong>Mobile Friendliness:<\/strong> Eliminates cumbersome pagination buttons, beneficial for mobile users.<\/li>\n<\/ul>\n<h2>Prerequisites<\/h2>\n<p>Before we dive into the implementation, make sure you have:<\/p>\n<ul>\n<li>A basic understanding of React.<\/li>\n<li>Node.js installed on your machine.<\/li>\n<li>A simple React application set up using <strong>Create React App<\/strong> or similar.<\/li>\n<\/ul>\n<h2>Setting Up the Project<\/h2>\n<p>Let\u2019s start by setting up a basic React application using <strong>Create React App<\/strong>. If you haven&#8217;t set up your project yet, you can do so with the following command:<\/p>\n<pre><code>npx create-react-app infinite-scroll-demo<\/code><\/pre>\n<p>Navigate into your project directory:<\/p>\n<pre><code>cd infinite-scroll-demo<\/code><\/pre>\n<h2>The Basic Structure<\/h2>\n<p>In this example, we&#8217;ll create a component called <strong>ImageList<\/strong> that fetches and displays images from an API. For demonstration purposes, we will use the <a href=\"https:\/\/jsonplaceholder.typicode.com\/photos\" target=\"_blank\">JSONPlaceholder photo API<\/a>, which returns a set of images for free.<\/p>\n<h3>Install Axios<\/h3>\n<p>To perform HTTP requests easily, let&#8217;s install Axios:<\/p>\n<pre><code>npm install axios<\/code><\/pre>\n<h3>Create ImageList Component<\/h3>\n<p>Create a new file called <strong>ImageList.js<\/strong> in the <strong>src<\/strong> folder:<\/p>\n<pre><code>touch src\/ImageList.js<\/code><\/pre>\n<p>Open <strong>ImageList.js<\/strong> and set up a basic functional component:<\/p>\n<pre><code>\nimport React, { useEffect, useState, useRef } from 'react';\nimport axios from 'axios';\n\nconst ImageList = () =&gt; {\n    const [images, setImages] = useState([]);\n    const [page, setPage] = useState(1);\n    const [loading, setLoading] = useState(false);\n    const observer = useRef();\n\n    \/\/ Fetch images when the component mounts or page changes\n    useEffect(() =&gt; {\n        const fetchImages = async () =&gt; {\n            setLoading(true);\n            const response = await axios.get(`https:\/\/jsonplaceholder.typicode.com\/photos?_page=${page}&amp;_limit=10`);\n            setImages(prev =&gt; [...prev, ...response.data]);\n            setLoading(false);\n        };\n        fetchImages();\n    }, [page]);\n\n    \/\/ Observer for infinite scroll\n    const lastImageRef = useRef();\n    useEffect(() =&gt; {\n        const options = {\n            root: null,\n            rootMargin: '0px',\n            threshold: 1.0\n        };\n\n        const callback = (entries) =&gt; {\n            if (entries[0].isIntersecting &amp;&amp; !loading) {\n                setPage(prevPage =&gt; prevPage + 1);\n            }\n        };\n\n        observer.current = new IntersectionObserver(callback, options);\n        if (lastImageRef.current) {\n            observer.current.observe(lastImageRef.current);\n        }\n\n        return () =&gt; {\n            if (lastImageRef.current) {\n                observer.current.unobserve(lastImageRef.current);\n            }\n        };\n    }, [lastImageRef, loading]);\n\n    return (\n        <div>\n            <h1>Infinite Scroll Images<\/h1>\n            <div>\n                {images.map((image, index) =&gt; (\n                    <img decoding=\"async\" src=\"{image.url}\" alt=\"{image.title}\" \/>\n                ))}\n            <\/div>\n            {loading &amp;&amp; <p>Loading more images...<\/p>}\n        <\/div>\n    );\n};\n\nexport default ImageList;\n<\/code><\/pre>\n<h2>Understanding the Code<\/h2>\n<p>Let&#8217;s break down the key concepts in the <strong>ImageList<\/strong> component:<\/p>\n<h3>1. State Management<\/h3>\n<p>We\u2019re using three pieces of state:<\/p>\n<ul>\n<li><strong>images:<\/strong> Stores the list of fetched images.<\/li>\n<li><strong>page:<\/strong> Controls the pagination of images being fetched.<\/li>\n<li><strong>loading:<\/strong> Manages the loading state when fetching more data.<\/li>\n<\/ul>\n<h3>2. Fetching Data<\/h3>\n<p>We use the <strong>useEffect<\/strong> hook to fetch images whenever the component mounts or the page state changes. We append new images to the existing array using the spread operator:<\/p>\n<pre><code>setImages(prev =&gt; [...prev, ...response.data]);<\/code><\/pre>\n<h3>3. Intersection Observer API<\/h3>\n<p>The Intersection Observer API allows us to detect when the last image comes into view. When the last image is visible, we increment the page number, triggering a new data fetch.<\/p>\n<h4>Setting Up the Intersection Observer<\/h4>\n<p>Inside another <strong>useEffect<\/strong> hook, we create and configure an intersection observer:<\/p>\n<pre><code>\nconst options = {\n    root: null,\n    rootMargin: '0px',\n    threshold: 1.0\n};\n<\/code><\/pre>\n<p>With this setup, we observe the last image in the image list. When it is in view, we increase the page number.<\/p>\n<h3>4. Cleanup<\/h3>\n<p>To prevent memory leaks, we unobserve the last image in the cleanup function of the effect:<\/p>\n<pre><code>\nreturn () =&gt; {\n    if (lastImageRef.current) {\n        observer.current.unobserve(lastImageRef.current);\n    }\n};\n<\/code><\/pre>\n<h2>Styling the Component<\/h2>\n<p>Let\u2019s add some basic styles for the image list. Create a new CSS file named <strong>ImageList.css<\/strong> and add the following CSS:<\/p>\n<pre><code>\n.image-list {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 10px;\n}\n\n.image-list img {\n    width: 100px;\n    height: auto;\n    border-radius: 5px;\n}\n<\/code><\/pre>\n<p>Be sure to import your CSS file in <strong>ImageList.js<\/strong>:<\/p>\n<pre><code>import '.\/ImageList.css';<\/code><\/pre>\n<h2>Integrating the Component<\/h2>\n<p>Finally, we need to integrate the <strong>ImageList<\/strong> component into our main application file. Open <strong>App.js<\/strong> and add the following code:<\/p>\n<pre><code>\nimport React from 'react';\nimport ImageList from '.\/ImageList';\n\nfunction App() {\n    return (\n        <div>\n            \n        <\/div>\n    );\n}\n\nexport default App;\n<\/code><\/pre>\n<h2>Testing the Implementation<\/h2>\n<p>Run your application using the command:<\/p>\n<pre><code>npm start<\/code><\/pre>\n<p>Once your app is running, you should see images being loaded seamlessly as you scroll down. The loading message will display while more images are being fetched.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we explored how to implement an infinite scroll feature in a React application using the Intersection Observer API. This is a powerful technique that can significantly enhance user experience when dealing with large lists of data. Feel free to experiment with different APIs or datasets, and customize the implementation based on your app&#8217;s needs.<\/p>\n<p>Happy coding!<\/p>\n<h2>Further Reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Intersection_Observer_API\" target=\"_blank\">MDN Web Docs &#8211; Intersection Observer API<\/a><\/li>\n<li><a href=\"https:\/\/reactjs.org\/docs\/hooks-intro.html\" target=\"_blank\">React Hooks Documentation<\/a><\/li>\n<li><a href=\"https:\/\/axios-http.com\/docs\/intro\" target=\"_blank\">Axios &#8211; Promise based HTTP client for the browser and Node.js<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Implementing Infinite Scroll in React Infinite scrolling is a user interface pattern that allows users to load more content as they scroll down a page. This technique is particularly useful for applications displaying large sets of data, such as photo galleries or list views, providing a seamless experience without the need for pagination. In this<\/p>\n","protected":false},"author":98,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[398],"tags":[224],"class_list":["post-7603","post","type-post","status-publish","format-standard","category-react","tag-react"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7603","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/users\/98"}],"replies":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/comments?post=7603"}],"version-history":[{"count":1,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7603\/revisions"}],"predecessor-version":[{"id":7604,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/7603\/revisions\/7604"}],"wp:attachment":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/media?parent=7603"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/categories?post=7603"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/tags?post=7603"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}