Jump to content
Search Community

Issue with React state update during drag event

drurustin test
Moderator Tag

Recommended Posts

Hi there,

 

I am creating an image slider using GSAP Draggable and React. I have added a slide counter so that when you drag or throw the slider the current slide index will display (1 of 3, 2 of 3 etc). The issue I'm running into is when I update the state during a throw (or drag) event. When the current slide update the animation (or drag) stops. I can't find a way around this and I'm not sure why it's stopping the animation. Thanks in advance for any help if anyone knows what the problem is. Here is my code:

 

import React, { useStateuseRefuseEffect } from 'react';
import { gsap } from 'gsap';
import Draggable from 'gsap/Draggable';
import InertiaPlugin from "../gsap/InertiaPlugin";
import "../styles/components/_Carousel.scss";
import Picture from './Picture';
 
gsap.registerPlugin(Draggable);
gsap.registerPlugin(InertiaPlugin);
 
const items = [
  "https://images.unsplash.com/photo-1558981822-0c0c5b070026?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=934&q=80",
  "https://images.unsplash.com/photo-1558981806-ec527fa84c39?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2250&q=80",
  "https://images.unsplash.com/photo-1558981420-87aa9dad1c89?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2250&q=80"
];
 
const Carousel = () => {
 
  const [curSlideupdateCurSlide] = useState(0);
  const [slideCountupdateSlideCount] = useState(0);
  const dragInstance = useRef(null);
  const dragTarget = useRef(null);
  const dragBounds = useRef(null);
  const itemsRef = useRef([]);
 
  useEffect(() => {
    updateSlideCount(itemsRef.current.length);
    dragInstance.current = Draggable.create(dragTarget.current, {
      type:"scroll",
      bounds: dragBounds,
      throwProps:true,
      dragClickables:true
    });
    // Cleanup
    return () => dragInstance.current[0].kill();
  }, []);
 
  const onThrow = (slide=> {
    console.log('im being thrown');
    let curSlideXPos = slide.getBoundingClientRect().left;
    let curSlideWidth = slide.getBoundingClientRect().width;
    console.log(slide);
    if (curSlideXPos < -Math.abs(curSlideWidth)) {
      updateCurSlide(curSlide + 1);
    }
  }
 
  useEffect(() => {
    dragInstance.current[0].addEventListener("throwupdate", () => {onThrow(itemsRef.current[curSlide])});
  }, [dragInstance]);
 
  const handleLoadedImage = (img=> {
    // TO DO
  }
 
  return (
    <div ref={dragBounds} className="carousel">
      <div>
        {curSlide + 1} of {slideCount}
      </div>
      <div ref={dragTarget} draggable="true" onDrag={(e=> {handleOnDrag(e)}} className="carousel__stage">
        {items.map((srci=> (
          <div ref={el => {itemsRef.current[i] = el}} key={i}>
            <Picture srcSetLargeDesktop={src} key={i} onLoad={handleLoadedImage} />
          </div>
        ))}
      </div>
      <div></div>
    </div>
  );
}
 
export default Carousel;

See the Pen rNygvyo by drurustin (@drurustin) on CodePen

Link to comment
Share on other sites

Thanks so much for taking a look at this and please excuse me, I'm a bit of a noob :)

 

I have tried to minimalise the demo so I hope that it makes a bit more sense now. Interestingly, I wasn't encountering the same issue as before but I've ran into a separate/new issue.

 

So when I throw the slider to the left and the current (first) slide is out of frame, the counter is meant to increment by 1 (from '1 of 3' to '2 of 3'). The issue seems to be with my updateCurSlide function. It doesn't seem to be updating the state correctly.

 

Not sure if this is now a React or GSAP issue. So confused. If you can offer any enlightenment that would be great but if the issue is with React then I understand that it's out of your domain. 

Link to comment
Share on other sites

Thanks for making the demo more clear!

 

33 minutes ago, drurustin said:

Not sure if this is now a React or GSAP issue.

 

I blame React. 😉

 

Your callback isn't keep current when the state changes. Here a couple different ways to handle GSAP callbacks that need to work with React values.

 

https://codesandbox.io/s/upbeat-rhodes-jp4r1?file=/src/App.js

 

https://codesandbox.io/s/musing-pine-wqlhs?file=/src/App.js

 

https://codesandbox.io/s/pensive-mirzakhani-gvfyl?file=/src/App.js

 

 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...