Jump to content
Search Community

Swapping between React components with their own animations

Daniel-HC test
Moderator Tag

Go to solution Solved by Cassie,

Recommended Posts

I have multiple "screens" (each in their own React component) that have their own animations. Each screen is made up of entirely different contents that take up the entire screen, so non-active screens need to be hidden (or unmounted). You can swap between the screens using the navigation at the top. 

 

Swapping between screens typically works, unless:

 

  1. You are swapping away from a screen whose animation tweens a number and sets the innerHTML of an element, AND
  2. This animation is not complete.

 

I've created a minimum demo here [https://codesandbox.io/s/quiet-water-qvze5w?file=/src/App.js]

 

To see the error, click to navigate to Screen 2 (which counts up to 5,000 over 10 seconds), and then switch BACK to Screen 1 before the animation is complete. 

 

The errors I get are:

Cannot set properties of null (setting 'innerHTML')

on line 13 of Screen2.js.

 

This error repeats thousands of times and halts the rest of the program from continuing.

 

A follow-up question, it seems like I should not be creating/destroying the screens based on whether they are active (by wrapping them in

{activeScreen === "screen1" && <Screen1 />}

, as this recreates the animation timelines every time I swap screens. (While it is fine in this simple demo, the screens in my actual app are much more complicated with many moving pieces.)

 

It would also be great to have the animations stay at their end/completion state so that when I swap back to a screen, it does not perform the animation again, but instead just shows the end of the animation. Any advice on that front would be very appreciated!

 

 

 

 

Edited by Daniel-HC
remove codesandbox link from codepen url box
Link to comment
Share on other sites

  • Solution

Hey there! Welcome.


So, from an error perspective, you'll maybe need to do a little cleanup?

https://codesandbox.io/s/cool-architecture-qr1vnx?file=/src/Screen1.js

 

I'm not really all too clued up on the best way to do stuff in react but if you want to skip to the end of your animations you're looking forprogress(1), then you'll need to add some conditional logic in to check if the animations have run before.

Something like this but with a global variable for didAnimate so your components don't refresh it each time

const didAnimate = useRef(false);
useEffect(() => {
  if (didAnimate.current) {
    return;
  }
  didAnimate.current = true;
  gsap.to(/* ... */)
}, [])


Happy to muddle through this with you, but it may be helpful to chat to React folks too. If so this discord is lovely and there's some really friendly React devs in there.

Link to comment
Share on other sites

Thanks so much! 

 

Changing from

tl = gsap.current.timeline()

to

 let tl = gsap.timeline()

enabled me to later perform tl.kill(), which did the trick. I was originally using gsap.current after reading the 'Using GSAP with React' tutorials -- but this prevented me from having access to tl.kill().

 

Thanks for the speedy response!!!

  • Like 1
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...