voronianski / react-swipe

:left_right_arrow: Swipe.js as a React component
http://voronianski.github.io/react-swipe/demo?continuous=true
MIT License
1.66k stars 256 forks source link

How to use this library with useState hook? #165

Open AlbertMontolio opened 4 years ago

AlbertMontolio commented 4 years ago

Description

I want to track the position of the slide in a state variable, so that I can use it in another component. The problem is, whenever I use setValue of the useState hook, all the page gets re-rendered.

Here is the code:

import React, {useEffect, useState} from 'react';
    import ReactDOM from 'react-dom';
    import ReactSwipe from 'react-swipe'
    import styled from 'styled-components'

    const StyledBox = styled.div`
      height: 50px;
      width: 100%;
      background-color: orange;
    `

    const Carousel = () => {
      let reactSwipeEl;

      const [position, setPosition] = useState(0)
      console.log('position', position)

      const swipeOptions = {
        continuous: false,
        transitionEnd() {
          setPosition(reactSwipeEl.getPos())
        }
      }

      return (
        <div>
          <ReactSwipe
            className="carousel"
            swipeOptions={swipeOptions}
            ref={el => (reactSwipeEl = el)}
          >
            <StyledBox>PANE 1</StyledBox>
            <StyledBox>PANE 2</StyledBox>
            <StyledBox>PANE 3</StyledBox>
          </ReactSwipe>
          <Circles>
            <Circle isActive={0 === position} />
            <Circle isActive={1 === position}/>
          </Circles>
        </div>
      );
    };

    export default Carousel
phil-linnell commented 4 years ago

I believe the component will re-render as you are updating state, but you just need to set the startSlide option to the current position in the swipeOptions so that it renders with the correct starting slide.

startSlide: position

Hope that helps.

cloud27 commented 3 years ago

I have this problem to ^^ I try startSlide and it works but we lost the animation.

jonborchardt commented 3 years ago

i get animations if i use transitionEnd instead of callback:

swipeOptions={{
    continuous: false,
    transitionEnd: (p) => setPage(p),
    startSlide: page,
}}
altmshfkgudtjr commented 2 years ago

When I proceeded in this way, there was an issue where ReactSwipe was re-rendered every time I swipe.

https://stackoverflow.com/questions/59887243/how-to-avoid-re-rendering-with-react-swipe-library-and-usestate

The following is a method using useMemo found on StackOverflow. You just need to wrap swipeOptions in useMemo.

const swiper = useRef(null);

const swipeOptions = useMemo(() => ({
  startSlide: 0,
  continuous: false,
}), []);

return (
  <ReactSwipe swipeOptions={swipeOptions} ref={swiper} >
    <StyledBox>PANE 1</StyledBox>
    <StyledBox>PANE 2</StyledBox>
    <StyledBox>PANE 3</StyledBox>
  </ReactSwipe>
);

or

const swiper = useRef(null);
const [position, setPosition] = useState(0)

const swipeOptions = useMemo(() => ({
  startSlide: position,
  continuous: false,
  transitionEnd: (index) => setPosition(index),
}));

return (
  <ReactSwipe swipeOptions={swipeOptions} ref={swiper} >
    <StyledBox>PANE 1</StyledBox>
    <StyledBox>PANE 2</StyledBox>
    <StyledBox>PANE 3</StyledBox>
  </ReactSwipe>
);