0

I'm trying to figure out how to make my Reactstrap carousel scroll up when I slide to the next or previous item.

This is exactly how I need it to work Bootstrap Carousel scroll top when slide But I did things in another way using reactstrap node module and I'm not quite getting how to make something like window.scrollTo(0,0) relate to the next and previous slide buttons.

Here goes the code:

import React, { useState, Component } from 'react';
import fotos2 from '../data/fotos2'

import {
  Carousel,
  CarouselItem,
  CarouselControl,
  CarouselIndicators,
  CarouselCaption
} from 'reactstrap';

const Example = (props) => {
  const [activeIndex, setActiveIndex] = useState(props.id);
  const [animating, setAnimating] = useState(false);

  const scrollTop = () => {
    window.scrollTo(0,0);
  };

  const next = () => {
    if (animating) return;
    const nextIndex = activeIndex === fotos2.length - 1 ? 0 : activeIndex + 1 || 
    setActiveIndex(nextIndex);
    scrollTop();
  }

  const previous = () => {
    if (animating) return;
    const nextIndex = activeIndex === 0 ? fotos2.length - 1 : activeIndex - 1;
    setActiveIndex(nextIndex);
    scrollTop();
  }

  const goToIndex = (newIndex) => {
    if (animating) return;
    setActiveIndex(newIndex);
  }

  const slides = fotos2.map((item) => {


    return (
      <CarouselItem data-pause="hover" style={{ minHeight: '20em' }}
        className="custom-tag"
        tag="div"
        key={item.url}
        onExiting={() => setAnimating(true)}
        onExited={() => setAnimating(false)}
      >
        {/* <img src={props.foto} alt={item.altText}/> */}
        <img className="imagenCarousel" src={item.url} alt={item.altText} />

        <CarouselCaption className="text-danger" captionText={item.caption} captionHeader={item.caption} />

      </CarouselItem>


    );
  });

  return (
    <div>

      {/* interval={false} para el slider */}
      <Carousel
        activeIndex={activeIndex}
        next={next}
        previous={previous}
        interval={false}
      >

        <CarouselIndicators items={fotos2} activeIndex={activeIndex} onClickHandler={goToIndex} />
        {slides}
        <CarouselControl direction="prev" directionText="Previous" onClickHandler={previous} />
        <CarouselControl direction="next" directionText="Next" onClickHandler={next} />
      </Carousel>
    </div>
  );
}

export default Example;

I already tried a couple solutions but it makes the main window scroll up instead of scrolling only the Modal that contains the carousel

Thank you in advance for your time !

2 Answers2

0

You need to call useEffect everytime make change to the activeIndex to scroll element to top.Try this and let me know if it works..

useEffect(()=>{window.scrollTop(0);},[activeIndex])

  • Hello, I tried using ```useEffect(()=>{window.scrollTo(0,0);},[activeIndex])``` but it makes the main window scroll up when I open the modal that contains the carousel. But it has to be close to this answer, thanks! – Federico Marchetta Aug 28 '20 at 13:39
0

If you read the docs you will see that scrollTo either accepts 2 parameters (x,y) or 1 parameter of type object. Your usage of window.scrollTo(0); will cause errors because it is not passing an object nor passing 2 parameters.

You can fix this by adding a second parameter for the y-axis:

const scrollTop = () => {
  window.scrollTo(0, 0);
};

In addition, your current implementation of scrolling to top right when next or previous is invoked will scroll the window to the top right away. If you want to retain the behavior on the Stack Overflow question you've linked (i.e., scroll-to-top after animation is done), you can opt to trigger the scrollTop function on onExited prop callback of CarouselItem component

<CarouselItem
    onExited={() => {
        setAnimating(false);
        scrollTop();
    }}
></CarouselItem>

CodeSandBox: https://codesandbox.io/s/heuristic-bird-n2vno?file=/src/App.js


The concept and logic is the same for the Modal overflow concerns. This time you can use Element.scroll - where Element is a React ref to the modal scrollable DOM element.

const containerRef = useRef(null);

const scrollTop = () => {
  // window.scrollTo(0, 0);
  containerRef.current.scroll(0, 0);
};

<div ref={containerRef}>

CodeSandBox: https://codesandbox.io/s/relaxed-mclaren-sklgp?file=/src/App.js

useRef hook: https://reactjs.org/docs/hooks-reference.html#useref

95faf8e76605e973
  • 13,643
  • 3
  • 24
  • 51
  • Hello!, thanks for your answer. It kinda works, the only thing is it scrolls the main window up instead of the content on the modal itself. But almost there – Federico Marchetta Aug 28 '20 at 13:22
  • @federico_531 The concept is the same. This time you can use [Element.scroll](https://developer.mozilla.org/en-US/docs/Web/API/Element/scroll) - where Element is a React ref to the modal scrollable DOM element. I've edited my answer to include this information and an example sand box. Hope this helps, good luck – 95faf8e76605e973 Aug 29 '20 at 05:36
  • Thanks!! it's now scrolling up only the content inside the element. But you know, the style of the content is a long photo without borders and it was working with only one scrollbar but now when the modal that contains the carousel opens up, I get double scroll bar and I have to be messing with both scroll bars to navigate throught the whole content. I fixed it by deleting the overlow: "auto" but scrollTop() stops working ! Any Idea what could it be? – Federico Marchetta Aug 29 '20 at 22:08
  • yes, you probably added another div with overflow properties. my sandbox was merely an example. re-use the modal's overflowing element - this is where you assign the `ref` to – 95faf8e76605e973 Aug 29 '20 at 23:30
  • Any progress? @federico_531 – 95faf8e76605e973 Sep 15 '20 at 08:22
  • No, thanks for asking. I left it aside for now because I needed to move on with other parts of the project and I'm also currently applying to get my first dev job so I've working on getting my portfolio ready. – Federico Marchetta Sep 15 '20 at 13:45