Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
drurustin

Issue with React state update during drag event

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 post
Share on other sites

Hey there,

Could you take a look at your resources in this pen and make sure they're linked correctly? Currently the pen's broken so it's a little tough to troubleshoot. 

Thanks!

Link to post
Share on other sites

I fixed some of the resources, but I still don't know what's going on in the pen. Can you please simplify it so it's obvious what the problem is? There is no need to load images or anything like that. Just a minimal demo. Thanks!

 

See the Pen bGqyzVj by GreenSock (@GreenSock) on CodePen

 

Link to post
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 post
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 post
Share on other sites

Thanks so much for the resources @OSUblake I'll work on it and aim to post a fix here to share with others.  I appreciate the support.

Link to post
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.

×