In this tutorial, we will build a Fullscreen Slider component with React Hooks. And to do that, we will create a custom hook to handle all the logic, then use it as a helper method to display the slides.
So, let's start by planning how our app will look like.
Sorry for the interrupt!
If you're interested in learning React in a comprehensive way, I highly recommend this bestseller course: React - The Complete Guide (incl Hooks, React Router, Redux)
It's an affiliate link, so by purchasing, you support the blog at the same time.Plan our app
To be able to follow along, you have to create a brand new React app by running the following command on your terminal:
npx create-react-app react-fullscreen-slider
Next, structure your project as follow:
├── App.js
├── App.test.js
├── components
| └── Slider.js
├── hooks
| └── useSlider.js
├── images.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
└── setupTests.js
As you can see, the folder structure is very simple. We have a components
folder which holds a file named Slider.js
, and another folder hooks
which keeps as you might guess the custom hook useSlider
, and an images.js
file which contain the images to show on the slider.
Now, let's add some lines of code into these files.
images.js
export default [
{
src: "https://drive.google.com/uc?id=1_oA9Sx4D4DhFrYBFQdL0I1CUIz_LhQue",
text: "Duis aute irure dolor in reprehenderit in voluptate velit esse",
},
{
src: "https://drive.google.com/uc?id=1rJFs-8So16UCiDag__hG4yyf_RnC08Fa",
text: "Consectetur adipisicing elit cillum dolore eu fugiat nulla",
},
{
src: "https://drive.google.com/uc?id=1HO2AGjd_1yyYI4pYTTBmGXBaWHoGSqCl",
text: "Asperiores ex animi explicabo cillum dolore eu fugiat nulla",
},
]
As I said earlier, this file holds the images. And each object has an image and a description. By the way, you can use a different approach to declare your images, it's totally up to you.
We have now the data to show, it's time to build the custom hook to handle the logic of the slider.
Let's do that
Creating the custom hook
The useSlider
function will receive three arguments: the image of the slide, the description and an array of images.
hooks/useSlider.js
import { useEffect } from 'react'
const useSlider = (slideImage, slideText, images) => {
let slideCounter = 0;
useEffect(() => startSlider())
const startSlider =() => {
slideImage.current.style.backgroundImage = `linear-gradient(
to right,
rgba(34, 34, 34, 0.4),
rgba(68, 68, 68, 0.4)
), url(${images[0].src})`;
slideText.current.innerHTML = images[0].text;
}
With these parameters in place, we can now create a new function startSlider()
and handle the first slide to display when the page finished loading.
Later, we will use useRef
to select elements and be able to manipulate the DOM (Document Object Model). But for now, just keep in mind that slideImage
and slideText
are references to DOM elements.
We can now access to the properties of these elements and start styling it. Here, we apply a linear gradient to the image, to well have a nice looking style, and next, append the corresponding text to the DOM.
hooks/useSlider.js
const handleSlide = slide => {
slideImage.current.style.backgroundImage = `linear-gradient(
to right,
rgba(34, 34, 34, 0.4),
rgba(68, 68, 68, 0.4)
), url(${images[slide - 1].src})`
slideText.current.innerHTML = images[slide - 1].text
animateSlide(slideImage)
}
const animateSlide = () => {
slideImage.current.classList.add("fadeIn")
setTimeout(() => {
slideImage.current.classList.remove("fadeIn")
}, 700)
}
Next, we use the same method with the function handleSlide()
by applying a linear gradient to the image. But this time, we receive as a parameter the number of the slide or counter if you want too, then use it to show the appropriate slide on the screen.
Next, we call the animateSlide()
method to well, animate it with a nice fade-in effect.
hooks/useSlider.js
const goToPreviousSlide = () => {
if (slideCounter === 0) {
handleSlide(images.length)
slideCounter = images.length;
}
handleSlide(slideCounter)
slideCounter--;
}
const goToNextSlide = () => {
if (slideCounter === images.length - 1) {
startSlider()
slideCounter = -1;
animateSlide(slideImage)
}
slideImage.current.style.backgroundImage = `linear-gradient(
to right,
rgba(34, 34, 34, 0.4),
rgba(68, 68, 68, 0.4)
),url(${images[slideCounter + 1].src})`;
slideText.current.innerHTML = images[slideCounter + 1].text;
slideCounter++;
animateSlide(slideImage)
}
return { goToPreviousSlide, goToNextSlide }
}
export default useSlider
As you can see, here, we have two main functions: goToPreviousSlide()
and goToNextSlide()
.
The first method goToPreviousSlide()
will check if the counter of the slide is equal to 0. And If it's the case, it will show the last slide, otherwise, it displays the previous one.
The second method will do the opposite. It checks if the counter of slides is equal to the last one and if it's the case, it will restart the slider, otherwise, the goToNextSlide()
method will show the next slide.
And to make everything accessible from another file, we have to return an object which contains goToPreviousSlide()
and goToNextSlide()
.
That being said, we can now move to the final part and use the custom hook to display the slider in the next section.
Display the slider
We already have the logic to show the slides, the only thing we have to do now is displaying them with Slider.js
.
Slider.js
import React, { useRef } from "react"
import useSlider from "../hooks/useSlider"
const Slider = ({ images }) => {
const slideImage = useRef(null)
const slideText = useRef(null)
const { goToPreviousSlide, goToNextSlide } = useSlider(
slideImage,
slideText,
images
)
return (
<div className="slider" ref={slideImage}>
<div className="slider--content">
<button onClick={goToPreviousSlide} className="slider__btn-left">
<i className="fas fa-angle-left"></i>
</button>
<div className="slider--feature">
<h1 className="feature--title">Dreaming</h1>
<p ref={slideText} className="feature--text"></p>
<button className="feature__btn">Get started</button>
</div>
<button onClick={goToNextSlide} className="slider__btn-right">
<i className="fas fa-angle-right"></i>
</button>
</div>
</div>
)
}
export default Slider
I forgot to mention it, but the CSS part will be not covered in this article, you can still find it in the Source Code. So, don't let these class names disturbing you.
The Slider()
function is relatively easy to implement since we already have useSlider
.
The only thing we have to do is importing useSlider
, then pull goToPreviousSlide()
and goToNextSlide()
without forgetting to pass the parameters as arguments to the function.
And as I said earlier, we have to use useRef
to access DOM elements.
With that change, we can now use the Slider component in the App.js
file and pass down the images array as props.
App.js
import React from "react"
import Slider from "./components/Slider"
import Images from "./images"
function App() {
return <Slider images={Images} />
}
export default App
And as you can see here, we just import the Images
and pass them as props to the Slider component.
With this tiny update, we have now done building a Fullscreen Slider component using React Hooks.
Thanks for reading!
You can find the source code here