Search code examples
reactjscreate-react-appreact-bootstrapreact-component

How to stack multiple carousel components on a single page in React?


In my React app I want to include 3 image carousels stacked on top of each other on a single page. I'm using a carousel component from React-Bootstrap which renders some image files saved locally in the public folder.

Here is a link to the source code from Bootstrap

TIA!

PS: Please explain your answer to me step-by-step as if you were talking to a 5 year old! I'm a complete beginner to coding and don't yet recognise most jargon!


Solution

  • Assumptions for my example:

    • I used 3 stacked carousels with 3 images each
    • Images are cycled through (if you reach first or last you "jump" to the other side)
    • Carousel images have no captions

    Setup UI and config the carousel:

    • Use an outer vertical stack to stack your slider/button sections and the go-back button
    • Use an inner horizontal stack to stack your two buttons and the slider
    • Configure each carousel as following:

    .

    <Carousel
        controls={false}
        indicators={false}
        interval={null}
        activeIndex={slidersState[x]}
    >
    
    • controls=false will hide the arrows on each side.
    • indicators=false will hider the "strokes" in the middle of the carousel.
    • interval=null will deactivate automatic sliding.

    Define the state and impement the logic:

    You will need such state, that can manage every of your carousel. In my example I'm giving every carousel an id and set the state to the first image (=0). Write two button onClick handlers - for going forward and back:

    const initialSlidersState = {
        1: 0,
        2: 0,
        3: 0
    };
    const [slidersState, setSlidersState] = React.useState(initialSlidersState);
    
    const nextSlide = (sliderId) => setSlidersState((prev) => {
      const currentIndex = prev[sliderId];
      let newIndex;
      if (currentIndex === 2) {
        newIndex = 0;
      } else {
        newIndex = currentIndex + 1;
      }
      return { ...prev, [sliderId]: newIndex };
    });
    
    const previousSlide = (sliderId) => setSlidersState((prev) => {
      const currentIndex = prev[sliderId];
      let newIndex;
      if (currentIndex === 0) {
        newIndex = 2;
      } else {
        newIndex = currentIndex - 1;
      }
      return { ...prev, [sliderId]: newIndex };
    });
    

    Of course this already works with dynamic amount of sliders and dynamic amount of images, but for the sake of simplicity I have used fixed amounts. For the buttons you could alternatively deactivate them, when reaching first/last image. Finally, you could also adopt the native controls from the carousel component, but it would go too far for this simple example.

    Please look into following code sandbox:

    https://codesandbox.io/s/eloquent-matsumoto-f8j1zf