DEV Community

Cover image for Build a Slider with React!
Ustariz Enzo
Ustariz Enzo

Posted on • Edited on

Build a Slider with React!

Hey fellow creators,

It's time to build an awesome slider with React!

If you prefer to watch the video version, it's right here :

Check out the source code here.

1. Create your component.

Create a Slider.js file, which will represent your component. You'll need to return each card from your upcoming data, so you'll need to use the .map() function in order to do that.
Since it's an example, the data are located in a dataSlider.js file.

import React, {useState} from 'react'
import './Slider.css'
import dataSlider from './dataSlider'

export default function Slider() {
   return (
        <div className="container-slider">
            {dataSlider.map((obj, index) => {
                return (
                        <img 
                        src={process.env.PUBLIC_URL + `/Imgs/img${index + 1}.jpg`} 
                        />
                )
            })}
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

What's all that code for the img tag you ask? Let's break that down:

  • for the link '/Imgs/img${index + 1}.jpg)' ⇒ you refer back to your ressources in a dynamic way, which is why you need to use the backticks as well as the ${}.
  • for process.env.PUBLIC_URL ⇒ this will be replaced by your application URL when you'll build your app. For the css, you'll need to add a div containing the img, like so:
<div className="slide">
    <img 
    src={process.env.PUBLIC_URL + `/Imgs/img${index + 1}.jpg`} 
    />
</div>
Enter fullscreen mode Exit fullscreen mode

To fix the error that shows up in the console, you need to add a key, which is a reference to dataSlider and its different ids, you can also use the handy "uuid" tool to do so :


<div
    key={obj.id}
    className={slideIndex === index + 1 ? "slide active-anim" : "slide"}
>
 ...
</div>
Enter fullscreen mode Exit fullscreen mode

Now the different images are there, you just can't see them. To remedy that, you need to add a component (which you'll create in a minute), twice, below the slider:

<BtnSlider />
<BtnSlider />
Enter fullscreen mode Exit fullscreen mode

2. Create the button component.

Create another file called BtnSlider.js which will be your buttons needed to go from one image to another.

Import the left and right arrow icons. Then, create a simple button with a classname, containing the image.

import React from "react";
import "./Slider.css";
import leftArrow from "./icons/left-arrow.svg";
import rightArrow from "./icons/right-arrow.svg";

export default function BtnSlider() {
  return (
    <button className="btn-slide">
      <img src={rightArrow} />
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

For now, there's no logic, we'll create some state and pass that state through the props to change the style of our button. Let's do it!

In your Slider.js file, add a const to be able to use the state:

const [slideIndex, setSlideIndex] = useState(1)
Enter fullscreen mode Exit fullscreen mode

Now create the nextSlide and the prevSlide functions, which for now will be empty :

const nextSlide = () => {

}

const prevSlide = () => {

}
Enter fullscreen mode Exit fullscreen mode

Then, you can pass it to your component BtnSlider, with the prop moveSlide. You also need to add the direction:

<BtnSlider moveSlide={nextSlide} direction={"next"} />
<BtnSlider moveSlide={prevSlide} direction={"prev"}/>
Enter fullscreen mode Exit fullscreen mode

Go back to your BtnSlider component and take them from the props. You can check it out in the console with a console log of course:

export default function BtnSlider({ direction, moveSlide }) {
  console.log(direction, moveSlide);
  return (
    <button className="btn-slide">
      <img src={rightArrow} />
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Then, you need to add an onClick to trigger the moveSlide from our props, and modify the classname of your button for the direction:

<button
      onClick={moveSlide}
      className={direction === "next" ? "btn-slide next" : "btn-slide prev"}
>
Enter fullscreen mode Exit fullscreen mode

Now as you can see, the arrows do appear but they're both the right arrow, which isn't what we want. Therefore you need to change the source for the image, with a condition:

<img src={direction === "next" ? rightArrow : leftArrow} />
Enter fullscreen mode Exit fullscreen mode

Here's what your full BtnSlider.js should look like:

import React from "react";
import "./Slider.css";
import leftArrow from "./icons/left-arrow.svg";
import rightArrow from "./icons/right-arrow.svg";

export default function BtnSlider({ direction, moveSlide }) {
  console.log(direction, moveSlide);
  return (
    <button
      onClick={moveSlide}
      className={direction === "next" ? "btn-slide next" : "btn-slide prev"}
    >
      <img src={direction === "next" ? rightArrow : leftArrow} />
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

3. Back to your slider!

Now it's time to change the classname for the div that returns our images. Replace "slide" with the following code:

<div
    key={obj.id}
    className={slideIndex === index + 1 ? "slide active-anim" : "slide"}
>
    <img 
    src={process.env.PUBLIC_URL + `/Imgs/img${index + 1}.jpg`} 
    />
</div>
Enter fullscreen mode Exit fullscreen mode

What does this mean? Well, you need to add + 1 each time since the index starts at 0. The condition is for the css, active-anim sets the opacity at 1.

Now you can see the images!

4. Create the logic of the slider.

Let's create the logic of our functions:

   const nextSlide = () => {
        if(slideIndex !== dataSlider.length){
            setSlideIndex(slideIndex + 1)
        } 
        else if (slideIndex === dataSlider.length){
            setSlideIndex(1)
        }
    }

    const prevSlide = () => {
        if(slideIndex !== 1){
            setSlideIndex(slideIndex - 1)
        }
        else if (slideIndex === 1){
            setSlideIndex(dataSlider.length)
        }
    }
Enter fullscreen mode Exit fullscreen mode

The first condition checks if slideIndex is inferior to 5 (since you only have five images), then it'll show the next image.

The second condition checks if you're at the last item of your array and if you are, then it'll reset back to the first image.

And vice versa for the second function. However, instead of putting setSlideIndex(5), it's better to put setSlideIndex(dataSlider.length), since the length of your array may change if you add an image for instance.

5. Add the dots at the bottom of the slider.

Let's create an empty array with a length of 5, in order to use the .map() function:

<div className="container-dots">
        {Array.from({length: 5}).map((item, index) => (
              <div classname="dot"></div>
         ))}
</div>
Enter fullscreen mode Exit fullscreen mode

But we do want some dynamic classname, in much the same way as we did for our arrows:

<div
    className={slideIndex === index + 1 ? "dot active" : "dot"}
></div>
Enter fullscreen mode Exit fullscreen mode

One last thing to add is the ability to click on it and for the image to change:

<div
    onClick={() => moveDot(index + 1)}
    className={slideIndex === index + 1 ? "dot active" : "dot"}
></div>
Enter fullscreen mode Exit fullscreen mode

Therefore you need to add this function that'll go to the appropriate image:

const moveDot = index => {
        setSlideIndex(index)
}
Enter fullscreen mode Exit fullscreen mode

Now make sure you use an anonymous function for the onClick, otherwise it'll trigger the moveDot function when the component is created, which is to say upon landing on the page, which isn't what we want of course!

Here's what your full Slider.js file looks like:

import React, {useState} from 'react'
import './Slider.css'
import BtnSlider from './BtnSlider'
import dataSlider from './dataSlider'

export default function Slider() {

    const [slideIndex, setSlideIndex] = useState(1)

    const nextSlide = () => {
        if(slideIndex !== dataSlider.length){
            setSlideIndex(slideIndex + 1)
        } 
        else if (slideIndex === dataSlider.length){
            setSlideIndex(1)
        }
    }

    const prevSlide = () => {
        if(slideIndex !== 1){
            setSlideIndex(slideIndex - 1)
        }
        else if (slideIndex === 1){
            setSlideIndex(dataSlider.length)
        }
    }

    const moveDot = index => {
        setSlideIndex(index)
    }

    return (
        <div className="container-slider">
            {dataSlider.map((obj, index) => {
                return (
                    <div
                    key={obj.id}
                    className={slideIndex === index + 1 ? "slide active-anim" : "slide"}
                    >
                        <img 
                        src={process.env.PUBLIC_URL + `/Imgs/img${index + 1}.jpg`} 
                        />
                    </div>
                )
            })}
            <BtnSlider moveSlide={nextSlide} direction={"next"} />
            <BtnSlider moveSlide={prevSlide} direction={"prev"}/>

            <div className="container-dots">
                {Array.from({length: 5}).map((item, index) => (
                    <div 
                    onClick={() => moveDot(index + 1)}
                    className={slideIndex === index + 1 ? "dot active" : "dot"}
                    ></div>
                ))}
            </div>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Well done! You now have an awesome slider for your website!

Drop some love by liking or commenting ♥

Come and take a look at my Youtube channel: https://www.youtube.com/c/TheWebSchool

See you very soon for other surprising tutorials!

Enzo.

Top comments (1)

Collapse
 
octodude500 profile image
OctoMonkeyFiveHundred

Thanks