Tutorial

How To Build an Infinite Scroll Image Gallery with React and CSS Grid

Published on December 12, 2019
author

William Imoh

How To Build an Infinite Scroll Image Gallery with React and CSS Grid

Introduction

In this tutorial, we will use the React frontend Javascript framework and CSS Grid to build an infinite scroll image gallery, using the Unsplash API to embed the photographic images. Using a codepen coding challenge from Scotch.io as a base for our code, we will use React.js to build out the interface, Axios to make the HTTP requests, and the react-infinite-scroll library to implement the infinite scroll feature.

Also, for this tutorial, we’ll employ React Hooks and use functional components throughout the project.

Prerequisites

For this tutorial, use this Image Collage Base code as your starting point to build your project upon.

Step 1 — Installing Required Packages

Import all required dependencies from a CDN. Codepen provides a search bar with which you can type in the name of the module, then select one from the result and add it to your project.

Dependencies installed are:

Go on to Unsplash to create an application and obtained an access key.

Step 2 — Building the Base Component

In React, the HTML template for the parent component is written in JSX. We shall proceed to write these HTML elements that make the template in JSX.

Create a functional component and render on the DOM with:

let Collage = () => {

    // Return JSX
  return (
    <div className="hero is-fullheight is-bold is-info">
      <div className="hero-body">
        <div className="container">
          <div className="header content">
            <h2 className="subtitle is-6">Code Challenge #16</h2>
            <h1 className="title is-1">
              Infinite Scroll Unsplash Code Challenge
            </h1>
          </div>
    // Images go here

        </div>
      </div>
    </div>
  );
};

// Render the component to the DOM element with ID of root
ReactDOM.render(<Collage />, document.getElementById("root"));

Here, you created the parent component Collage , returned the HTML elements in JSX, and rendered it in the DOM element with an ID of root. Bulma classes were used to provide basic styling of the page.

Step 3 — Building a Single Image Component

Next, let’s move on to creating a single component for a single fetched image. This will help us set the position of each image.

Create a single functional component with:

const UnsplashImage = ({ url, key }) => (
  <div className="image-item" key={key} >
    <img src={url} />
  </div>
);

This component receives props of url and key, which are the URL of the image to be displayed and the key for each rendered image. In the component, we use the <img/> element to display the fetched image.

Step 4 — Fetching and Rendering Random Images from Unsplash

Unsplash provides a free API to fetch random images. The images will be stored in a state container and passed to the DOM from state. Since we’ll use React Hooks, we’ll handle state and lifecycle methods with useState and useEffect, respectively.

In the Collage component, create two state variables, one to hold the incoming images and the other to store a boolean that tells the program if the images are loaded or not.

[...]

const [images, setImages] = React.useState([]);
const [loaded, setIsLoaded] = React.useState(false);

[...]

Next, we’ll create a function that fetches 10 random images using Axios. This is done by making a GET request to the API endpoint while passing your obtained access key and the amount of images you want returned. Do this with:

const fetchImages = (count = 10) => {
    const apiRoot = "https://api.unsplash.com";
    const accessKey = "{input access key here}";

    axios
      .get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
      .then (res => {
        setImages([...images, ...res.data]);
        setIsLoaded(true);
      });
};

Axios is a promise-based library, and on the resolution of the request, we use the setImages method to fill in the images fetched, as well as spread any previous images fetched. Also, we set the value of loaded to true.

Now that we have images stored in state, let’s call this fetchImages function once the component is mounted. In earlier versions of React, we would do this with the componentDidMount lifecycle method. However, React now provides the useEffect hook to handle all lifecycle operations in a functional component.

In the Collage component, call fetchImages on mount with:

[...]

React.useEffect(() => {
    fetchImages();
}, []);

[...]

The useEffect hook takes a second parameter, which is an array. The provided function in the hook will run every time the array is updated or modified.

Now you have a page that fetches ten random images from Unsplash. Let’s proceed to render the images in an infinite scroll container.

React-infinite-scroll-component provides the ability to display a loading spinner or any element as a placeholder, call a function to fetch more data once the loader is in view or approaches view, and displays any specified data. In the returned JSX of Collage and after the div with a class of header, render the images in the infinite scroll component with:

<InfiniteScroll
     dataLength={images}
     next={() => fetchImages(5)}
     hasMore={true}
     loader={
      <img
         src="https://res.cloudinary.com/chuloo/image/upload/v1550093026/scotch-logo-gif_jq4tgr.gif"
         alt="loading"
      />}
 >
     <div className="image-grid" style={{ marginTop: "30px" }}>
        {loaded ? 
            images.map((image, index) => (
                <UnsplashImage url={image.urls.regular} key={index} />
            )): ""}
    </div>
</InfiniteScroll>

In the InfiniteScroll component, we passed a function to the next parameter. The function calls the fetchImages function and passes a parameter of 5, which is the number of images to be fetched. In the loader parameter, we passed an image in JSX to serve as the loading placeholder.

.map() is used to iterate through the images array in state and renders each image using the UnsplashImage component.

We’ll use CSS grid to style the images fetched. Edit the CSS to this:

.title {
  font-family: 'Carter One';
}
.container {
  margin-top: 50px;
  text-align: center;
}

.image-grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  grid-auto-rows: minmax(50px, auto);

  .image-item:nth-child(5n){
    grid-column-end: span 2;
  }

  img{
    display: flex;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

This creates a grid with columns with a width of 250px and fills the entire image container. Also, the rows are set to have a minimum of 50px and a maximum of auto to fit each image. We used the grid-column-end property on every fifth image to make it take up two image spaces instead of one.

The object-fit property ensures each image fits or contains the full size of its container.

You can find the completed gallery here https://codepen.io/Chuloo/full/BMPXqy.

Conclusion

In this tutorial, we built out an image gallery using React hooks, as well as using CSS grid. You can try to play around with the grid to create an even better setup.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
William Imoh

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more