DEV Community

Cover image for Creating an Image Slider with the UseState Hook
Otebele Jemimah
Otebele Jemimah

Posted on

Creating an Image Slider with the UseState Hook

In my last article, we discussed the useState() hook and did a simple example. You could wonder "How do I use this in a real-life project"? I've got you, newbie. We'll be creating an image slider that renders a new image when we click on some buttons. Have a sneak peek below:

Finished

Code repository for this project to follow along

First, we install React since we need useState() hook from the React library. I use Vite to bundle React since it's recommended by the React team. Open a terminal and write the command below then follow the instructions shown in your command line thereafter:

npm create vite@latest image-slider-app -- --template react

Delete the index.css file. Clear the App.jsx and App.css file as we would create new components and write our styles.

First, let's create our component. Since it's a simple app, we would be creating just one component that contains the images and arrows. Write the below code in the App.jsx file

import "./App.css";
import back from "./assets/back.svg";
import next from "./assets/next.svg";

function App() {
  return (
    <main>
      <section>
        <div>
          <img
            src={back}
            alt=""
            width={50}
            height={50}
            className="icon-left"
          />

          <img
            src={next}
            alt=""
            width={50}
            height={50}
            className="icon-right"
          />
          <img src="https://i.pinimg.com/originals/10/11/bc/1011bcc380b230ecb422589c990e38ec.jpg" alt="" className="main-image" />
        </div>
      </section>
    </main>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

The code above consists of our sliding image and the arrows we use to change them. You can find these arrows in the code repository I posted above. In the first line, we can find the CSS import but we don't have our styles yet. Well, I'm so generous and I decided to share the CSS styles below so our project looks good.

*,
::after,
::before {
  margin: 0;
  box-sizing: border-box;
  padding: 0;
}

main section {
  width: 100%;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

main section div {
  width: 100%;
  max-width: 700px;
  position: relative;
  margin: 2rem;
}

main section div img.main-image {
  width: 100%;
  height: 500px;
  object-fit: cover;
}

.icon-left {
  position: absolute;
  top: 50%;
  left: -3%;
}

.icon-right {
  position: absolute;
  top: 50%;
  right: -3%;
}

Enter fullscreen mode Exit fullscreen mode

We have the following result

what we have without adding state

Hold up! We're clicking the buttons but the images are not changing. Why?

💡 Remember, anytime we need to change a state that reflects in the user interface, we use the useState() hook. This guarantees that our state and user interface are in sync.

Do you remember what we do first? Yeah! We import the useState() hook in the top level(first line in the App.jsx file)

import { useState } from 'react'

After importing it, we need to initialize it in our app. We do this by saying:

const [activeImage, setActiveImage] = useState(0)

Let's think about the logic we'll be using in this simple app. Firstly, we need 5 images. When we click the next button, the image moves to the next one and when we click previous it moves back. Seems like something our dear useState() can help us with since we also want to see the changes in the interface.

Now where do we get 5 images? Well, I got you. I made an array of 5 images src that we're going to make us of in this practical

const imagesArray = [
  "https://i.pinimg.com/originals/e6/72/c9/e672c9fe478daac0019c9235e3a9794c.jpg",
  "https://i.pinimg.com/originals/10/11/bc/1011bcc380b230ecb422589c990e38ec.jpg",
  "https://littlelosttravel.com/wp-content/uploads/2020/11/Finland.jpg",
  "https://littlelosttravel.com/wp-content/uploads/2020/11/Hawaii-jelle-de-gie-u.jpg",
  " https://littlelosttravel.com/wp-content/uploads/2020/11/Morocco-sergey-pesterev-u.jpg",
];

Enter fullscreen mode Exit fullscreen mode

We don't add this inside the App(), we add it just after importing useState() from React at the top level. Why? Surely our state would always change, meaning the component would be re-rendered. When this happens, everything inside the function App() {} would be created again. It has little or no effect in this case since imagesArray is not a large chunk of data, but re-rendering, especially large data affects performance. There's a solution to this but it's beyond the scope of this article.

Now we have our images src, we also need to add event listeners to our arrow so that whenever we click on them, they change accordingly.

<img
            src={back}
            alt=""
            width={50}
            height={50}
            className="icon-left"
            onClick={goToPreviousImage}
          />

          <img
            src={next}
            alt=""
            width={50}
            height={50}
            className="icon-right"
            onClick={goToNextImage}
          />
Enter fullscreen mode Exit fullscreen mode

We have our event listeners and the respective functions they should call when they're clicked on. Now let's make those functions work.

For the function that goes to the next image, we have this:

  const goToNextImage = () => {
    setActiveImage(activeImage + 1);
console.log(activeImage)
  };
Enter fullscreen mode Exit fullscreen mode

This increments the activeImage by one anytime the next arrow is clicked.

 const goToPreviousImage = () => {
    setActiveImage(activeImage - 1);
console.log(activeImage)
  };
Enter fullscreen mode Exit fullscreen mode

This decrements the activeImage by one anytime the previous arrow is clicked.

Before testing out our features, we need to make sure the image index shown corresponds with the activeImage number. Back to our App.jsx file, just before the closing div, we change the src of the image to imagesArray[activeImage]. Why? The activeImage state is a number which we use to represent the index of the image since we're using an array. For example, on entering the App for the first time, the activeImage state is 0(as we initialized it) so following our logic we have imagesArray[0] which renders the first image in the array. So now for our main image we have
<img src={imagesArray[activeImage]} alt="" />

We also console.log() the activeImage when the arrow is clicked so we can see how it really works. Now we have this:
result

Well... it works and broke halfway. From what we can see the activeImage reads more than the available index in the array. For example, we have just 5 items in our array, so the highest index we can get is 4. But the active index reads to infinity as far as we click. For the previous array, it reads less than 0(since we said it should be decremented) and we know from our knowledge of javascript, an array index can't be negative. That's why we have codes breaking.

What can we do to solve this problem? Well, we can need to add an if statement. When the activeImage count is more than the last index in the array, we want to set it back to 0 and when the activeImage count is less than 0, we want to set it back to the index of the last item in the array. See the code snippet below:

const goToNextImage = () => {
     if (activeImage === imagesArray.length - 1) {
       setActiveImage(0);
      return;
     }
    setActiveImage(activeImage + 1);
    console.log(activeImage);
  };

  const goToPreviousImage = () => {
     if (activeImage === 0) {
      setActiveImage(imagesArray.length - 1);
     return;
     }
    setActiveImage(activeImage - 1);
    console.log(activeImage);
  };
Enter fullscreen mode Exit fullscreen mode

With this, our issue should be fixed. Let's see...

result

Yeah!! We did it, and now it works. When the activeImage is more than the index available in the array, it automatically sets the activeImage to 0 and when the `activeImage is less than 0, it sets it back to the index of the last item in the array.

Well, we did it! Our image slider works the way it should. If you were quite confused about how useState() actually works, here is a previous article:

https://dev.to/jemmycodes/usestate-hook-demystified-4gi5

Follow me so I can use written words to simplify the mysteries behind React and Javascript! Don't forget to Like, comment and share!

Top comments (2)

Collapse
 
poriaspec profile image
PEACE IRABOR • Edited

Another Article Well Written.
Thank you for adding the a link to the code repo too.
Welldone 👏👏👏👏

Collapse
 
qbentil profile image
Bentil Shadrack

Wow…. This is gold Meemah👏
This is really helpful.
Thank you