Creating a Carousel component using React Hooks and SASS

This article was born out of a need I had a few months ago while working on a web project. I needed to create a carousel component in the page without adding another npm package into the mix of the already bloated project 😉, I decided to document the process of creating the carousel to remind my future self and to help someone who may need it someday.

carogif.gif

Prerequisite Knowledge: You should be familiar with Javascript, ReactJs, and usage of React Hooks, working knowledge of SASS or CSS is also needed.

Note: you have to install Nodejs on your computer

Project setup

On your favorite terminal run

npx create-react-app carousl

the command bootstraps a React app having this structure when opened in the text editor.

Carousl
   node_modules
   public
      index.html
      ...
   src
      index.js
      App.js
      ...
  package.json
  ...

Creating the Card component

On the terminal, run the following (while in the root folder of the project)

touch src/Card.js src/Card.scss

this creates two files inside the src folder, inside the Card.js file, add the following lines of code:

import React from "react";
import './Card.scss';

const Card = ({ name }: props) => {
  return (
    <div className='card'>
      <p className='text'>{name}</p>
    </div>
  );
};

export default Card;

Note that the Card component is expecting a name props to be passed into it

const Card = ({ name }): props => {

this is needed so as to give different names to the cards that will be rendered on the page. The name will be passed into it from the parent component later.

Inside the Card.scss file, add these styles

.card {
  background-color: black;
  min-width: 49%;
  max-width: 50%;
  height: 28vh;
  text-align: center;
  margin-right: 10px;
  border-radius: 12px;

  .text {
    color: white;
  }
}

When you think about a carousel, you'd realize it's mainly about scrolling the cards to be displayed to a user with the use of an arrow from left to right; that is exactly the approach employed in the creation of the carousel component here.

Let's begin, download the arrow that will be used to control the cards inside the carousel component. You can also decide to use an Icon from one of the many icons services like Fontawesome, but for this tutorial, SVG files were downloaded, create an asset folder inside src to keep the files, like this

mkdir src/asset

Inside the App.js file, replace the code in it with the following lines of code.

import React, { useRef } from "react";
import Card from "./Card";
import "./App.scss";
import leftCircle from "./asset/leftarrow.svg";
import rightCircle from "./asset/img_92071.png";

const CardArray = [
  { name: "first card" },
  { name: "second card" },
  { name: "third card" },
  { name: "fourth card" },
  { name: "fifth card" },
  { name: "sixth card" },
  { name: "seventh card" },
];

function App() {
  let carouslRef = useRef(null);

  return (
    <div className= 'carousel'>
      <button className='direction' onClick={prev}>
        <img className='arrow' src={leftCircle} alt="left button" />
      </button>
      <div className='card-div'>
        <main className='card-scroll' ref={carouslRef}>
          {CardArray.map((carousel, i) => (
            <Card {...carousel} key={i} />
          ))}
        </main>
      </div>
      <button className='direction' onClick={next}>
        <img className='arrow' src={rightCircle} alt="right button" />
      </button>
    </div>
  );
}

export default App;

The code above has a few things I'd like to explain briefly, first is the useRef Hook introduced to ReactJs in version 16.8.

React hooks allow you to use state and other React features without writing a class - reactjs.org

The usage of refs in Reactjs was traditionally meant to allow the developer to directly access an HTML element in the DOM(document object model) and carry out an operation on the particular element. Before hook, there would have been a need to write out the exact function to be performed using normal Javascript syntax, but with the introduction of the useRef hook, it now allows us to pass the action in ReactJs directly as will be seen in the next code block. More info on this can be gotten here.

Also, note that the variable housing the hook in question

 let carouslRef = useRef(null);

was called on the carousel class

<main className='card-scroll' ref={carouslRef}>

Adding the following code to the App.scss file

.carousel {
  display: flex;
  margin: 20rem 15rem;

  .direction {
    background: none;
    border: none;
    outline: none;
    padding: 0;
    width: 10%;

    .arrow {
      width: 50%;
    }
  }

  .card-div {
    width: 50vw;

    .card-scroll {
      display: flex;
      overflow: hidden;
    }
  }
}

we are presented with this simple, UI for our carousel

Screenshot 2020-11-25 at 22.53.16.png

Recheck the App.js file, you'll notice the button tags having an onClick action. They both refer to functions next and prev which holds the logic behind the forward and backward movement of the carousel.

Let's add that now, inside the App.js file, add the following snippet of code inside the App function before the return statement


const prev = () => {
    carouslRef &&
      carouslRef.current &&
      carouslRef.current.scrollTo({
        behavior: "smooth",
        top: 0,
        left:
          carouslRef.current.scrollLeft - carouslRef.current.clientWidth * 0.5,
      });
  };

  const next = () => {
    carouslRef &&
      carouslRef.current &&
      carouslRef.current.scrollTo({
        behavior: "smooth",
        top: 0,
        left:
          carouslRef.current.scrollLeft + carouslRef.current.clientWidth * 0.5,
      });
  };

With this function written, the button begins to move as the cards as intended.

Thanks for reading up to this point, if you find this helpful, kindly give some likes, also, if there's a better way this could have been implemented, kindly let's discuss via the comment section.

The code is hosted on Github here.

No Comments Yet