DEV Community

Discussion on: Help with Image Click Through (Like a Carousel) using React Hooks

Collapse
mitchelln11 profile image
mitchelln11 Author

For those who might come across this later, I figured out my own problem.

  1. We are use state, so import React with useState:

import React, { useState } from 'react';

  1. Create your main function that you will be exporting
function Carousel() {
}

OR *(If you're going by ES6)*

const Carousel = () => {
}
  1. Inside the function, create your variable as an object (Not actually changing state, so we don't need a function to change anything.(Make sure your image paths are correct)
    const [slides] = useState([
        {
            source: "../images/img1.jpg",
            title: "Image 1"
        },
        {
            source: "../images/img2.jpg",
            title: "Image 2"
        },
        {
            source: "../images/img3.jpg",
            title: "Image 3"
        }
    ]);
  1. Typically, when we set images, we'd do something like this:
<img src="../images/img1.jpg" alt="Image 1" title="Image 1" className="slider-img" />

But because it's React, we want the images to be dynamic, so we should opt for something like this:

<img src={currentSlide.source} alt={currentSlide.title} title={currentSlide.title} className="slider-img" />
  1. The above won't do anything yet, because currentSlide is not declared. Now we have to set defaults.
    let [currentPosition, setCurrentPosition] = useState(0); // Initial slide index value
    let currentSlide = slides[currentPosition]; // variable index value we can reference later

Because we want to change something, we need another variable to act as our indexer(currentPosition). I had issues when setting this to const, so even though though React Docs use const, the variable is changing, so I changed it to let to get past the error of setting it to const.

currentPosition is my indexer
currentslide is all of my information inside each index of the slides variable object.

With this, the first image should display on the page. (That is assuming your image paths are correct. I might try hard-coding an image tag just to see that you have the correct path)

  1. Now that we have an image up, we want to be able to move from one to another. In our
   )


We add arrows. (I'm adding arrows from fontawesome inside of div tags.)

<div id="arrow-left" onClick={arrowLeftClick}><i className="fas fa-arrow-alt-circle-left"></i></div>
<div id="arrow-right" onClick={arrowRightClick}><i className="fas fa-arrow-alt-circle-right"></i></div>
  1. If you noticed, there's on onClick that will run functions (arrowLeftClick, arrowRightClick), let's create those. Here's both.
    const arrowRightClick = () => {
        currentPosition !== slides.length -1 ? // Check index length
        setCurrentPosition(currentPosition + 1) : setCurrentPosition(currentPosition = 0);
        currentSlide = slides[currentPosition];
    }

This is actually a ternary operator.
We are asking for a boolean condition
I've been taught put the more complex stuff first because it's less likely to hit.
We are starting out at 0 as our index, but we have to make up for after we get past the last image.
If the current position is not at the last image,

currentPosition !== slides.length -1

If that's true (not at the last image, img3.jpg in this case)

?

increase our index by 1, we're also doing this by running our setCurrentPosition we set earlier.

setCurrentPosition(currentPosition + 1)

If the case is false, (Is at the last image, img3.jpg)

:

go back to the first image, or the 0 index.

setCurrentPosition(currentPosition = 0);

Now update the slide with the following:

currentSlide = slides[currentPosition];

Here is the left click below, which really does the same thing, conditionals are just slightly different.

    const arrowLeftClick = () => {
        currentPosition !== 0 ? // Check index length
        setCurrentPosition(currentPosition - 1) : setCurrentPosition(currentPosition = slides.length - 1);
        currentSlide = slides[currentPosition];
    }

This doesn't have the CSS attached, but I think you can change it to however you would like.
Here's the full code:

import React, { useState } from 'react';

const Carousel = () => {

    const [slides] = useState([
        {
            source: "../images/img1.jpg",
            title: "Half Moon Pier"
        },
        {
            source: "../images/img2.jpg",
            title: "Port Washington Rocks"
        },
        {
            source: "../images/img3.jpg",
            title: "Abandoned Rail"
        }
    ]);

    // SET CAROUSEL DEFAULTS
    let [currentPosition, setCurrentPosition] = useState(0); // Initial slide index value
    let currentSlide = slides[currentPosition]; // variable index value we can reference later

    const arrowRightClick = () => {
        currentPosition !== slides.length -1 ? // Check index length
        setCurrentPosition(currentPosition + 1) : setCurrentPosition(currentPosition = 0);
        currentSlide = slides[currentPosition];
    }

    const arrowLeftClick = () => {
        currentPosition !== 0 ? // Check index length
        setCurrentPosition(currentPosition - 1) : setCurrentPosition(currentPosition = slides.length - 1);
        currentSlide = slides[currentPosition];
    }

    return (
        <div className="carousel-block">
            <div className="flex-container">
                <div id="slider">
                    <div className="slide">
                        <img src={currentSlide.source} alt={currentSlide.title} title={currentSlide.title} className="slider-img" />
                        <div className="arrows">
                            <div id="arrow-left" onClick={arrowLeftClick}><i className="fas fa-arrow-alt-circle-left"></i></div>
                            <div id="arrow-right" onClick={arrowRightClick}><i className="fas fa-arrow-alt-circle-right"></i></div>
                        </div>
                    </div>

                </div>
            </div>
        </div>
    )
}

export default Carousel;