Framer-motion drag not respecting previously updated props

  framer-motion, javascript

A simple use-case is to allow a user to either click buttons to paginate in a slider, or drag. Both events call the same paginate function with a param to either go forward or back–simple stuff.

However, the trigger from drag seems to cause bizarre behavior where the slider wants to start the animation from several slides back as if it ignores the updated props. This doesn’t happen when using the buttons and both use the same simple paginate call.

Any tips appreciated.

Minimal example:

export default function App() {
  const [position, setPosition] = useState<number>(0);

  const paginate = (direction: Direction) => {
    setPosition((prev) => {
      return direction === Direction.Forward
        ? Math.max(-800, prev - 200)
        : Math.min(0, prev + 200);
    });
  };

  return (
    <div className="App">
      <Slider>
        <Wrapper
          animate={{ x: position }}
          transition={{
            x: { duration: 1, type: "tween" }
          }}
          drag="x"
          dragConstraints={{
            top: 0,
            left: 0,
            right: 0,
            bottom: 0
          }}
          onDragEnd={(e, { offset, velocity }) => {
            const swipe = swipePower(offset.x, velocity.x);

            if (swipe < -swipeConfidenceThreshold) {
              paginate(Direction.Forward);
            } else if (swipe > swipeConfidenceThreshold) {
              paginate(Direction.Back);
            }
          }}
        >
          <Slide>1</Slide>
          <Slide className="alt">2</Slide>
          <Slide>3</Slide>
          <Slide className="alt">4</Slide>
          <Slide>5</Slide>
        </Wrapper>
      </Slider>
      <button onClick={() => paginate(Direction.Back)}>prev</button>
      <button onClick={() => paginate(Direction.Forward)}>next</button>
    </div>
  );
}

Codesandbox Demo

Source: Ask Javascript Questions

LEAVE A COMMENT