'react-bootstrap Carousel breaks when changing content during transition

video of issue:

enter image description here

When the carousel is transitioning from one slide to another, if another entry from a dataset is choosen, before the slide finishes its transition, the new images are rendered, but controls/timer are broken, so the carousel is not slidable any more (manually or automatically).

activeFish is a useState object with some fish data that gets changed with setActiveFish(newActiveFishDataObject) when a list item is clicked

Anyone have ideas for a solution?

  <Carousel>
    {activeFish['Image Gallery'].map((imageData, i) => (
        <Carousel.Item key={imageData.title + i}>
            <div className="image-container">
                <img
                    className="d-block w-100" 
                    src={imageData.src}
                    alt={imageData.alt}
                />
            </div>
            <Carousel.Caption>
                <p>{imageData.title}</p>
            </Carousel.Caption>
        </Carousel.Item>
    ))}
</Carousel>  

Replicate- https://codesandbox.io/s/frosty-night-yckxro (thanks to @IgorGonak)

onload, immediately click the down arrow on the dropdown to expose options, mouse over option b, wait for transition to happen, click b rite in the middle of the transition. observe controls wont work for the 'b' dataset



Solution 1:[1]

I've created a dummy data with three entries and three images each entry. Then I built a select to select one and the carousel like yours - it is working on my side: When I choose another entry, the images in carousel are adjusted. The transition is working and is performed after each defined timeout:

https://codesandbox.io/s/frosty-night-yckxro

import React from "react";
import { Carousel, Form, Stack } from "react-bootstrap";
import data from "./fishData";

export default function App() {
  const [activeFish, setActiveFish] = React.useState(data[0]);
  const onSelect = (event) => {
    const choosenFishName = event.target.value;
    const choosenFish = data.find((fish) => fish.name === choosenFishName);
    setActiveFish(choosenFish);
  };
  return (
    <Stack className="m-3">
      <Form.Group id="fish-select" className="mb-3" style={{ width: "18rem" }}>
        <Form.Select value={activeFish.name} onChange={onSelect}>
          {data.map((entry) => (
            <option key={entry.name} value={entry.name}>
              {entry.name}
            </option>
          ))}
        </Form.Select>
      </Form.Group>
      <p>Choosen fish is: {activeFish.name}</p>
      <Carousel style={{ height: 200, width: 300 }}>
        {activeFish["Image Gallery"].map((img) => {
          return (
            <Carousel.Item key={img.title}>
              <img className="d-block w-100" src={img.src} alt={img.alt} />
              <Carousel.Caption>{img.title}</Carousel.Caption>
            </Carousel.Item>
          );
        })}
      </Carousel>
    </Stack>
  );
}

Edit:

According to https://github.com/react-bootstrap/react-bootstrap/issues/6352 the problem here is that there is a state called "isSliding" in Carousel component. If it's true, the controls are deactivated. When we change children while sliding "isSliding" is true, but it's not set to false in the end, because the appropriate callback is never fired.

The solution is to reset the component by adding unique key to it:

<Carousel
    key={activeFish.name}
    interval={2000}
    style={{ height: 200, width: 300 }}
>
    {activeFish["Image Gallery"].map((img) => {
      return (
        <Carousel.Item key={img.title}>
          <img className="d-block w-100" src={img.src} alt={img.alt} />
          <Carousel.Caption>{img.title}</Carousel.Caption>
        </Carousel.Item>
      );
    })}
</Carousel>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1