bitworking / react-gsap

React components for GSAP
https://bitworking.github.io/react-gsap/
Other
568 stars 33 forks source link

Sequence of semi-complex nested Timelines breaks with manual control in the master Timeline #22

Open CSMR-DB opened 4 years ago

CSMR-DB commented 4 years ago

I have a few different Scenes constructed using their own Timelines and 1 master Timeline taking care of sequencing the different scenes. Every scene may or may not use a forwardRef markup as showcased in the Advanced Multiple Targets section. It looks something like this:

<>
  {/* <StyledControlsWrapper>
    <Controls playState={PlayState.stop}> */}
      <Stage>
        <Timeline 
          labels={[
            { label: 'scene1', position: 0 },
            { label: 'scene2', position: 1 },
            { label: 'scene3', position: 2 },
            etc...,
          ]}
          playState={playing ? PlayState.play : PlayState.pause}
          totalProgress={progress}
          paused={true} 
        >
          {/* <Scene1/> */}
          {/* <Scene2/> */}
          <Scene3/>
        </Timeline>
      </Stage>
    {/* </Controls>
  </StyledControlsWrapper> */}
  <button onClick={() => setPlaying(!playing)}>
    {playing ? "Pause" : "Play"}
  </button>
  <div>
    <input
      type="range"
      min="0"
      max="1"
      step="0.001"
      value={progress}
      onChange={(event: React.ChangeEvent<HTMLInputElement>): void => setProgress(parseFloat(event.target.value))}
    />
  </div>
</>

This issue has to do with me currying props into forwardRef components. The manual control just completely breaks the sequence. However, when I use the provided Controls wrapper, all is fine. Makes me think that the curried forwardRef is not the issue per se. New CodeSandbox example: uncomment both the Control tags to see what is happening.

bitworking commented 3 years ago

I had to look at this more deeply. Maybe this will be fixed with version 3, when I change the way how Timeline targets refs are added.

bitworking commented 3 years ago

This is a hard one. Still not fixed in 3.1.0.

bitworking commented 3 years ago

The problem is that the target change with every rerender. You can prevent this by using a useMemo hook:

const CurriedForwardedTimelineTargetMarkup: React.ForwardRefExoticComponent<React.RefAttributes<
    any
  >> = useMemo(() => CurriedForwardedTimelineTarget({ text }), [text]);

I'll mark this issue as enhancement and try to make it work with changing targets.