Bootstrap carousel: sets active item to first when data changes (Reactjs)

Viewed 635

My carousel with data.img is an array of link img

   <div
        id="carouselExampleControls"
        className="codeinfo__carousel carousel slide"
        data-bs-ride="carousel"
      >
        <div className="carousel-inner">
          <div className="carousel-item active">
            <img
              src={data.img[0]}
              className="codeinfo__img d-block w-100"
              alt="..."
            />
          </div>
          {data.img.map(
            (e, i) =>
              i > 1 && (
                <div className="carousel-item">
                  <img
                    src={e}
                    className="codeinfo__img d-block w-100"
                    alt="..."
                  />
                  {i}
                </div>
              )
          )}
        </div>
        <button
          className="carousel-control-prev"
          type="button"
          data-bs-target="#carouselExampleControls"
          data-bs-slide="prev"
        >
          <span className="carousel-control-prev-icon" aria-hidden="true" />
          <span className="visually-hidden">Previous</span>
        </button>
        <button
          className="carousel-control-next"
          type="button"
          data-bs-target="#carouselExampleControls"
          data-bs-slide="next"
        >
          <span className="carousel-control-next-icon" aria-hidden="true" />
          <span className="visually-hidden">Next</span>
        </button>
      </div>

When the data has changed, the active item does not return to the first item, but to the number of the previous active item. So if the length of the previous data.img is bigger than the length of the current data.img there will be nothing to display and the carousel will crash.(sorry for my english, I use google translate)
Like the example below. How to make class "active" return first item?
carousel1 > Change data > carousel2

1 Answers

I solved the problem myself. I removed all bootstrap actions and select active item using react code. I use useState to select active item, setInterval to autoPlay, useEffect to reset activity to 0. Here is my code:

const Carousel = (props) => {
  const data = props.data;
  const [nowActive, setNowActive] = useState(0);
  const [onHover, setOnHover] = useState(false);

  // autoplay (stop in hover)
    useEffect(() => {
    if (!onHover && data !== null) {
      let i = nowActive;
      const timer = setInterval(() => {
          if (i >= data.img.length - 1) {
            setNowActive(0);
            i = 1;
          } else {
            setNowActive((prev) => prev + 1);
            i = i + 1;
          }
      }, 3000);
      return () => {
        clearTimeout(timer);
      };
    }
  }, [onHover, data]);

  // change data >> return active = 0
  useEffect(() => {
    setNowActive(0);
  }, [data]);

  const carousel = () => {
    return (
      <div
        id="carouselExampleControls"
        className="codeinfo__carousel carousel slide"
        data-bs-ride="carousel"
        onMouseOver={() => setOnHover(true)}
        onMouseLeave={() => setOnHover(false)}
      >
        <div className="carousel-inner">
          {data.img.map((e, i) => (
            <div className={"carousel-item " + (nowActive === i && "active")}>
              <img src={e} className="codeinfo__img d-block w-100" alt="..." />
            </div>
          ))}
        </div>

        <button
          className="carousel-control-prev"
          type="button"
          onClick={() => {
            nowActive === 0
              ? setNowActive(data.img.length - 1)
              : setNowActive(nowActive - 1);
          }}
        >
          <span className="carousel-control-prev-icon" aria-hidden="true" />
          <span className="visually-hidden">Previous</span>
        </button>

        <button
          className="carousel-control-next"
          type="button"
          onClick={() => {
            nowActive === data.img.length - 1
              ? setNowActive(0)
              : setNowActive(nowActive + 1);
          }}
        >
          <span className="carousel-control-next-icon" aria-hidden="true" />
          <span className="visually-hidden">Next</span>
        </button>
      </div>
    );
  };

  return data !== null ? 
    <div>{carousel()}</div> :    
    <div>Null data</div>

Note: Although the problem has been solved, but this carousel does not have any Animation Effect when changing slides:

enter image description here

Related