Search code examples
reactjsreact-hooksmaterial-uifrontendstyled-components

How do I manage scroll position on a react mui component with button clicks?


I have a long list of images that I want to be able to click through using custom buttons. I have a parent element that serves as a window to view these images. I can set the parent element to 'scroll', but I'm having a hard time figuring out how to manage the state click events. Here is the trimmed down version of my problem:

const CarouselDisplay = ({ prev, next, ...props }) => {
  // translate state
  const [scroll, setScroll] = useState(0);

 
  // Handle click events
  const prevHandler = () => {
    
  };

  const nextHandler = () => {
  
  };



  return (
    <StyledRoot scroll={scroll}>
      <CarouselButton prev={prev} onClick={prevHandler} />
      <CarouselButton next={next} onClick={nextHandler} />
      {/* <CarouselList translate={shift} /> */}
      <CarouselList />
    </StyledRoot>
  );
};

const StyledRoot = styled(Box)({
  position: 'relative',
  marginBottom: '.5rem',
  background: 'transparent',

  overflow: 'hidden',
  overflowX: 'scroll',
  scrollbarWidth: 'thin',
});

export default CarouselDisplay;

With the vision of the list component going way off the screen to the right, then translating it on the button click events, I tried getting the widths of the window component and the list component (using refs and layoutEffect) in order to dynamically calculate all the precise translate movements. Unfortunately, React or MUI will not render the entire list component that would otherwise protrude way off the right side of the screen. So when I tried calculating the width of the list component, it equated to the width of my parent window component.


Solution

  • This one will help you

    const CarouselDisplay = ({ images, ...props }) => {
      const carouselRef = useRef(null);
    
      const prevHandler = () => {
        if (carouselRef.current) {
          carouselRef.current.scrollLeft -= carouselRef.current.offsetWidth;
        }
      };
    
      const nextHandler = () => {
        if (carouselRef.current) {
          carouselRef.current.scrollLeft += carouselRef.current.offsetWidth;
        }
      };
    
      return (
        <StyledRoot ref={carouselRef}>
          <CarouselButton prev onClick={prevHandler} />
          <CarouselButton next onClick={nextHandler} />
          <CarouselList images={images} />
        </StyledRoot>
      );
    };
    
    const StyledRoot = styled(Box)({
      position: 'relative',
      marginBottom: '.5rem',
      background: 'transparent',
    
      overflow: 'hidden',
      overflowX: 'scroll',
      scrollbarWidth: 'thin',
    });
    
    export default CarouselDisplay;