1

I am a beginner in using ReactJS/NextJS. I am creating a carousel component to use an Image optimization feature in NextJS Framework. The carousel component works fine and I want to add carousel next slide automatically when a props for duration will be passed. I was trying to create a function inside UseEffect hook with setTimeout to perform my next slide.

I tried this code:

import React, { useState, useEffect } from 'react';
import styles from 'components/shared/carousel/carouselStyles.css';
import NavigateBeforeIcon from '@material-ui/icons/NavigateBefore';
import NavigateNextIcon from '@material-ui/icons/NavigateNext';
import Image from 'next/image';

const Carousel = (props) => {
  const { slides, slideshow } = props;

  const [current, setCurrent] = useState(0);

  const length = slides && slides.length;

  const nextSlide = () => {
    setCurrent(current === length - 1 ? 0 : current + 1);
  };

  const prevSlide = () => {
    setCurrent(current === 0 ? length - 1 : current - 1);
  };

  if (!Array.isArray(slides) || slides.length <= 0) {
    return null;
  }

  useEffect(() => {
    if (slideshow > 0) {
      let interval = setInterval(() => {
        nextSlide();
      }, slideshow);
      return () => clearInterval(interval);
    }
  }, [current, slideshow]);

  return (
    <section className="slider">
      <NavigateBeforeIcon className="left-arrow" onClick={prevSlide} />
      <NavigateNextIcon className="right-arrow" onClick={nextSlide} />
      {slides.map((slide, index) => {
        return (
          <>
            <div
              className={index === current ? 'slide active' : 'slide'}
              key={index}
            >
              {index === current && (
                <Image
                  src={slide.feature_image}
                  alt="carousel_img"
                  className="image"
                  width={1600}
                  height={600}
                />
              )}
            </div>
          </>
        );
      })}
      <div className="dots-con">
        {slides.map((slide, index) => {
          return (
            <span
              className={index === current ? 'dot active' : 'dot'}
              key={index}
            ></span>
          );
        })}
      </div>
    </section>
  );
};

export default Carousel;

but this gives me error of Error: Rendered more hooks than during the previous render

If I will comment the useEffect, then it works fine but doesn't came up with what I want which is to auto-play the carousel

2 Answers 2

3

move your condition after hook like this:

  useEffect(() => {
    if (slideshow > 0) {
      let interval = setInterval(() => {
        nextSlide();
      }, slideshow);
      return () => clearInterval(interval);
    }
  }, [current, slideshow]);


 if (!Array.isArray(slides) || slides.length <= 0) {
        return null;
 }

read more here about react hook rules link

Sign up to request clarification or add additional context in comments.

Comments

0

It is a syntax issue in your useEffect Hook.

You should not wrap the written statement inside if condition. It never executes the return of useEffect to clean up.

useEffect(() => {
    let interval;
    if (slideshow > 0) {
      interval = setInterval(() => {
        nextSlide();
      }, slideshow);
    }
    return () => {
      clearInterval(interval);
    };
  }, [current, slideshow]);

1 Comment

share a code sandbox link for more detail

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.