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>
)
}
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>
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>
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 />
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>
);
}
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)
Now create the nextSlide and the prevSlide functions, which for now will be empty :
const nextSlide = () => {
}
const prevSlide = () => {
}
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"}/>
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>
);
}
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"}
>
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} />
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>
);
}
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>
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)
}
}
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>
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>
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>
Therefore you need to add this function that'll go to the appropriate image:
const moveDot = index => {
setSlideIndex(index)
}
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>
)
}
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)
Thanks