Creating an Image Slider with the UseState Hook
Tags: javascript, react, beginners
Published: 2023-06-04 16:48:54

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1r7atjapvzk8z6pvlm0.gif)

> [Code repository for this project to follow along](https://github.com/jemmycodes/technical-writing-code-snippets/tree/main/image-slider-app)
 

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

```jsx
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;
```
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.

```css
*,
::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%;
}

```
We have the following result

![what we have without adding state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dko9yg3phv6ndit93ao7.gif)

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

```js
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",
];

```
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.

``` html
<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}
          />
```
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: 

```jsx
  const goToNextImage = () => {
    setActiveImage(activeImage + 1);
console.log(activeImage)
  };
```
This increments the `activeImage` by one anytime the next arrow is clicked. 

```jsx
 const goToPreviousImage = () => {
    setActiveImage(activeImage - 1);
console.log(activeImage)
  };
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnj169nl18c2m6s3ohrf.gif)

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: 

```jsx
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);
  };
```
With this, our issue should be fixed. Let's see...

![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m62iajlaj827et31vrfu.gif)

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](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!