azazdeaz / react-gsap-enhancer

Use the full power of React and GSAP together
MIT License
727 stars 38 forks source link

Modifying ANY properties of an animated component causes onComplete to re-fire even after animation complete #24

Closed iDVB closed 7 years ago

iDVB commented 8 years ago

We have a weird issue where modifying any properties of a component that GSAP-enhancer is using in an animation causes that animation's onComplete to re-fire even if the animation is already long-since completed.

Going one step further, if we have a setState() inside that onComplete, it's causing things to infinitely re-render.

Is it not possible to use the onComplete callback AND edit a components properties when its being used in an animation?

You can see below that we are passing data.videoId into VideoBox below which is a dynamic value that changes based on user interaction and usually happens AFTER animating in the VideoBox. So it seems very odd that updating that prop is causing the onComplete to re-fire each time?!

    return (
      <div className="OurPeople" style={styles.base}>
          <h1 name="heading" style={styles.h1}>
            <SVGText2 x={8.9+'em'} y={1+'em'} viewBox='0 0 500 40'>Our People</SVGText2>
          </h1>

          <VideoBox name="player" videoId={data.videoId} opts={data.opts} style={[styles.player]} />

          <div style={carouselStyles.base}>
            <Slider {...sliderOptions}>{slides}</Slider>
          </div>

      </div>
    );

Animation code:

  _handleAnimationComplete(){
    console.log('INTRO ANIMATION COMPLETE!!!');
    // this.setState({
    //   introComplete: true,
    // });
  }

  _transitionAnim({target}) {
    const self = this,
          duration = 0.3;

    return new TimelineMax({paused: false, onComplete: this._handleAnimationComplete, onReverseComplete: this._handleAnimationReverseComplete})
      .add('in')
      .from(target.find({name: 'player'}), duration, {
        //rotation: '180',
        transform: 'translateY(50em)',
        opacity: '0',
      }, 'in')
      .from(target.find({name: 'heading'}), duration, {
        transform: 'translateX(50em)',
        opacity: '0',
      }, 'in');
  }
iDVB commented 8 years ago

bump?

azazdeaz commented 8 years ago

Hi, sorry for the late response i did not catch the problem from the script you provided. Can you help with a working example? This pen could be used as a boilerplate.

iDVB commented 8 years ago

I think we've narrowed down the culprit. Although, I'm not sure how to fix. It appears that when the GSAP'd component renders, it causes all animations in that component to restart again. But since most are already animated to the end...it simply just fires the onComplete. Here is the example Pen.

Looking at your original code, you can prevent the issue by, calling

  componentDidUpdate() {
     this.switchAnim.tweenTo('label')
  }

However, your _appearAnim Tween would likely not be able to do that since its a Tween and not a Timeline. Also, we're having a hard time figuring out how to effectively do a .tweenFrom since it is a "from" animation we are trying to handle.

Regardless.... this all seems pretty weird... why are the animations reanimating by default with every componentDidUpdate?

azazdeaz commented 8 years ago

Hi, thanks four your help on this. The fixed version is published on npm under v0.3. Please let me know if you have any further issues (and also if it works for you too :) )

azazdeaz commented 8 years ago

I updated this demo to preview this fix: http://azazdeaz.github.io/react-gsap-enhancer/#/demo/add-events-with-controller

iDVB commented 7 years ago

Sorry, this is an old issue that I was unable to confirm your fix. Feel free to close, or maybe someone else can verify.