Savio Martin

Creating an Image search app using Unsplash API with infinite scrolling 📸

Created April 9, 2021

Hello Folks 👋

This is Savio here. I'm young dev with an intention to enhance as a successful web developer. I love building web apps with React. I have proved my superiority in frontend technologies.

Today, I'm super pumped to build an amazing Image search app using Unsplash API with infinite scrolling. So, let's get started ✌


Table of contents

Setting up Unsplash API

  1. To set up Unsplash API for your app, head over to https://unsplash.com/developers and create an account 👤 scrnli_4_9_2021_11-00-46 AM.png

  2. After creating an account, go to your apps section. Here you could see your app. Now, create a new app by clicking New Application button. scrnli_08_04_2021_20-25-06.png

  3. Now accept all terms, this would create an app for you scrnli_08_04_2021_20-26-00.png

  4. You will be redirected to your app, here when you scroll you can see a section called Keys 🔑. Here you can see your access key, just save it for later. We are gonna use this. scrnli_08_04_2021_20-26-57.png

Let's Start Coding

So, it is time to get into coding our app. So, take your coffee and start coding! ⚡ First of all, let's create a react app by copy-pasting this code in the terminal.

npx create-react-app unsplash-image-search

Getting Into the project directory

cd unsplash-image-search/

Here are the dependencies that we use for our project 👩‍💻

  1. Axios
  2. react-infinite-scroll-component

Let's install all the dependencies using NPM.

npm i axios react-infinite-scroll-component

Starting our server ✨

npm start

Now we can see our app running in localhost:3000

welcome-to-react.png

Now, we can clear some unwanted files in our src/ folder. (this is optional). I am removing all the files except App.js, index.js and index.css. I am also clearing the default code.

So, let's first start with App.js. We can create 2 variables, this would help in fetching images using Unsplash API 📸

const client_id = "YOUR_ACCESS_KEY";
const fetchUrl = `https://api.unsplash.com/search/photos?client_id=${client_id}&query=${query}&page=${page}`;

and next we're setting some useState hooks.

const [data, setData] = useState([]);
const [query, setQuery] = useState("code");
const [page, setPage] = useState(1);
const [hasMore, setHasMore] = useState(true);

Now, create a function to fetch Images through Unsplash API. We are also gonna use axios that make the work faster. We are also increasing the page number after a load setPage(page + 1), this act important for infinite scrolling. Here goes the desired function 👇

const fetchImages = () => {
    axios
      .get(fetchUrl, {
        headers: {},
      })
      .then((response) => {
        setData([...data, ...response.data.results]);
      })
      .catch((error) => {
        console.log(error);
      });
    setPage(page + 1);
  };

Now, lets create a useEffect hook that would run whenever query is changed. Here goes the code 👇

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

Now, lets return all our components. It consists of a input and the InfiniteScroll wrapper. Inside InfiniteScroll wrapper, we map all images. 📷

return (
    <div className="App flex">
      <input
        type="text"
        onKeyDown={(e) => searchImages(e)}
        placeholder="Search For Images 🔎"
      />
      <InfiniteScroll
        dataLength={data.length}
        next={fetchImages}
        hasMore={hasMore}
        loader={<p>Load more...</p>}
        endMessage={
          <p style={{ textAlign: "center" }}>
            <b>Yay! You have seen it all</b>
          </p>
        }
      >
        <div className="main flex">
          {data.map((data, key) => (
            <div className="container" key={key}>
              <img
                src={data.urls.small}
                className="image"
                alt={data.alt_description}
              />
              <h4>Photo by {data.user.name} 📸</h4>
            </div>
          ))}
        </div>
      </InfiniteScroll>
    </div>
  );

We also want to update our query on every enter click on the input. For that we're gonna use a new function.

const searchImages = (e) => {
    if (e.keyCode === 13) {
      setQuery(e.target.value);
      setData([]);
    }
  };

So, the work of App.js is finished. Here goes the complete code 👇

App.js

import axios from "axios";
import { useEffect, useState } from "react";
import InfiniteScroll from "react-infinite-scroll-component";
import "./App.css";

function App() {
  const [data, setData] = useState([]);
  const [query, setQuery] = useState("code");
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);

  const client_id = "4mB0CC1xdwTfTQGjF1v1uO9vS2Z8ubzBPd4X0B86IEU";
  const fetchUrl = `https://api.unsplash.com/search/photos?client_id=${client_id}&query=${query}&page=${page}`;

  const fetchImages = () => {
    axios
      .get(fetchUrl, {
        headers: {},
      })
      .then((response) => {
        setData([...data, ...response.data.results]);
      })
      .catch((error) => {
        console.log(error);
      });
    setPage(page + 1);
  };
  const searchImages = (e) => {
    if (e.keyCode === 13) {
      setQuery(e.target.value);
      setData([]);
    }
  };

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

  return (
    <div className="App flex">
      <input
        type="text"
        onKeyDown={(e) => searchImages(e)}
        placeholder="Search For Images 🔎"
      />
      <InfiniteScroll
        dataLength={data.length}
        next={fetchImages}
        hasMore={hasMore}
        loader={<p>Load more...</p>}
        endMessage={
          <p style={{ textAlign: "center" }}>
            <b>Yay! You have seen it all</b>
          </p>
        }
      >
        <div className="main flex">
          {data.map((data, key) => (
            <div className="container" key={key}>
              <img
                src={data.urls.small}
                className="image"
                alt={data.alt_description}
              />
              <h4>Photo by {data.user.name} 📸</h4>
            </div>
          ))}
        </div>
      </InfiniteScroll>
    </div>
  );
}

export default App;

Now, our app is working but our app lacks beauty. So, lets style our app 🎨.

App.css

@import url(https://fonts.googleapis.com/css?family=Poppins:100,100italic,200,200italic,300,300italic,regular,italic,500,500italic,600,600italic,700,700italic,800,800italic,900,900italic);

* {
  margin: 0;
  padding: 0;
  font-family: "Poppins", sans-serif;
}
body {
  background: #f5effc;
}
.App {
  flex-direction: column;
}
.image {
  width: 363px;
  border-radius: 5px;
  height: 240px;
}
.container {
  border-radius: 5px;
  margin: 5px;
  padding: 15px;
  box-shadow: 0 10px 40px -10px rgb(0 64 128 / 10%);
  border: 1px solid #eee;
  background: #f9fafc;
}
h4 {
  font-weight: 400;
}
.flex {
  display: flex;
  align-items: center;
  justify-content: center;
}
.main {
  width: 100%;
  height: 100%;
  flex-wrap: wrap;
}
input {
  padding: 10px;
  box-shadow: 0 10px 40px -10px rgb(0 64 128 / 10%);
  border: 1px solid #ddd;
  background: #f9fafc;
  width: 40%;
  margin: 15px 0;
}

Congrats 🎉, You have now finished working on our app. Our app is now working perfectly as expected. You did it, it was so fast! Our app now looks like this 👇

Here is the code sandbox demo 💻

I have also deployed the app, Here goes the live demo 🚀 https://unsplash-image-search-app.vercel.app/

Here is the full source code, don't forget to star the repository 🌟 https://github.com/saviomartin/unsplash-image-search-app


👀 Wrapping Up

Yeah, that's a wrap. Hope you enjoyed the article. Do not hesitate to share your feedback. I am on Twitter @saviomartin7. Give a follow!

Follow me on Github @saviomartin, Don't miss my amazing projects! 💯

I hope you learned to use Unsplash API and created an image search app, now go start building amazing apps. Feedbacks are greatly appreciated! 🙌

Have an amazing day!

🌎 Lets connect

🙌 Support

My projects are fueled by coffees ☕, get one for me!

Buy Me A Coffee saviomartin