Open In App

Build an Image Search App with Infinite Scroll using React JS

Last Updated : 11 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

This article delves into building a React-based image search app with infinite scroll. Users can search for images based on a query, and as they scroll down, additional images are fetched and shown. The Unsplash API is employed for searching and retrieving these images, resulting in a fully operational image search app with an integrated infinite scroll feature by the end of the tutorial.

Prerequisites:

Approach to create Image Search App:

Utilizing the Unsplash API, we’ll retrieve images according to the user’s search input. Implementing a debounced search input ensures delayed API requests during typing pauses. Additionally, an infinite scroll feature loads more images as the user reaches the page’s bottom, accompanied by a preloader spinner. The state management and required actions are facilitated through the useState, useEffect, and useRef hooks.

Steps to Create React App and Installing modules:

Step 1: Create the project file using the command:

npx create-react-app <<Name_of_project>>

Step 2: Navigate to the folder using the command

cd <<Name_of_project>>

Step 3: Install the following packages

npm install unsplash-js lodash react-spinners

Modules:

  • unsplash-js: to interact with Unsplash this API.
  • lodash: to use debounce utility function.
  • react-spinners: to show spinner while fetching images.

Project Structure:

Untitled

project structure

The updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-spinners": "^0.13.8",
"unsplash-js": "^7.0.18",
"web-vitals": "^2.1.4"
}

Note: Get your Unsplash API key from https://unsplash.com/

Example: Write the following code in respective files.

  • App.js: This file contains the main logic.
  • App.css: This file contains the styling.

Javascript




// App.js
import "./App.css";
import { useState, useEffect, useRef } from "react";
import { createApi } from "unsplash-js";
import { debounce } from "lodash";
import { BounceLoader } from "react-spinners";
 
const unsplash = createApi({
    accessKey: << use your API Key>>,
});
 
function App() {
 
    // State variable to store the search phrase
    const [phrase, setPhrase] = useState("");
 
    // Ref to hold the current value of the search phrase
    const phraseRef = useRef(phrase);
 
    // State variable to store the fetched images
    const [images, setImages] = useState([]);
 
    // Ref to hold the current value of the fetched images
    const imagesRef = useRef(images);
 
    // State variable to indicate if images are being fetched
    const [fetching, setFetching] = useState(false);
 
    // Ref to hold the current value of the fetching state
    const fetchingRef = useRef(fetching);
 
    function getUnsplashImages(query, page = 1) {
        setFetching(true);
        fetchingRef.current = true;
        return new Promise((resolve, reject) => {
            unsplash.search
                .getPhotos({
                    query,
                    page,
                    perPage: 5,
                })
                .then((result) => {
 
                    // Update fetching state to indicate
                    //that images fetching is completed
                    setFetching(false);
                    fetchingRef.current = false;
                    resolve(result.response.results.map((result) =>
                        result.urls.regular));
                });
        });
    }
 
    useEffect(() => {
        phraseRef.current = phrase;
        if (phrase !== "")
            debounce(() => {
                setImages([]);
                getUnsplashImages(phrase, 1).then((images) => {
                    setImages(images);
                });
                imagesRef.current = images;
            }, 1000)();
    }, [phrase]);
 
    function handleScroll(e) {
        const { scrollHeight, scrollTop, clientHeight } =
            e.target.scrollingElement;
        const isBottom = scrollHeight - scrollTop <= clientHeight;
        if (isBottom && !fetchingRef.current) {
            getUnsplashImages(
                phraseRef.current,
                imagesRef.current.length / 5 + 1
            ).then((newImages) => {
                imagesRef.current = [...imagesRef.current, ...newImages];
                setImages(imagesRef.current);
            });
        }
    }
    useEffect(() => {
        document.addEventListener("scroll", handleScroll, { passive: true });
        return () =>
            document.removeEventListener("scroll", handleScroll);
    }, []);
 
    return (
        <div>
            <input
                type="text"
                value={phrase}
                onChange={(e) => setPhrase(e.target.value)}
            />
            <br />
            {images.length > 0 && images.map((url) =>
                <img src={url} />)}
            <div>
                {fetching && (
                    <div style={{ textAlign: "center" }}>
                        <BounceLoader speedMultiplier={5}
                            color="#000000" />
                    </div>
                )}
            </div>
        </div>
    );
}
 
export default App;


CSS




/* App.css  */
img {
  max-width: 100%;
}


Steps to Run the Application:

Step 1: Type the following command in the terminal of your project directory

npm start

Output: Type the following URL in your web browser http://localhost:3000/

ezgifcom-video-to-gif-(3)

image search app



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads