Jump to content
Search Community

Timeline Reverse not working in React with GSAP 3

KaranM test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hey! GSAP community, I'm a new guy here and Loved the GSAP features.

But I'm facing issue while using timeline reverse() in my react project.

here is my codesandBox's Link => https://codesandbox.io/s/determined-pine.....

 

Let me explain the issue:

Problem lies In MobileNav component, when using timeline reverse method.

I'm using ToggleMenu() method to change the state of isMenuOpen, and  according to that executing tl.play() and tl.reverse().

tl.play() works fine but tl.reverse() not.

Help Me.

A comment is also added there in file where I'm facing issue

 

Note:-

Please Open the preview of website in new tab and resize around 400px as I'm using matchMedia to show different component version of Navbar,

Otherwise . 

 

Link to comment
Share on other sites

  • Solution

Hi and welcome to the GreenSock forums.

 

There are a few things that are causing the issue.

 

You're adding instances to the timeline inside a useEffect() hook that is called every time the menu is toggled, so basically you're creating the timeline over and over again. The first time the timeline takes the elements and update their styles to what you want, by the second time the timeline is created and it updates the styles to the indicated values, but in the first run the timeline already set those values in the elements, so nothing happens. In this type of situations (toggle animations) is better to move all the code that adds animations to a timeline, to an useEffect hook that runs only in the first render, using an empty dependencies array. Then store the timeline in a specific reference in order to keep it through future re-renders. Finally handle the timeline toggle inside a specific useEffect hook. This seems to be doing what you want:

const tl = useRef(gsap.timeline({ defaults: { ease: "power2.inOut" } }).reverse());
const [isMenuOpen, ToggleMenu] = useState(false);

useEffect(() => {
  tl.current.to([activatorRef.current], {
    background: "#805ad5",
    borderRadius: "0 5em 5em 0"
  });
  tl.current.to(
    [navItemContainerRef.current],
    {
      clipPath: "ellipse(100% 100% at 50% 50%)"
    },
    "-=.5"
  );

  tl.current.to(
    [navItemIconRefs.current],
    {
      opacity: 1,
      transform: "translateX(0)",
      stagger: 0.5
    },
    "-=.5"
  );
}, []);

useEffect(() => {
  tl.current.reversed(!isMenuOpen);
}, [isMenuOpen]);

Happy Tweening!!!

  • Like 2
Link to comment
Share on other sites

Thanks a lot for reply,

This works absolutely fine and I understood that I was recreating the instance of the timeline on every toggle.

 

After posting this question I also came around with another answer of yours on same problem, here's that link:https://greensock.com/forums/topic/21379-cant-get-reverse-to-work-in-react/

 

 

 

Also if possible can you shed the light on this line of code where you're using .reverse() method while creating ref, what other methodscan be possibly come here in other situations.

const tl = useRef(gsap.timeline({ defaults: { ease: "power2.inOut" } }).reverse());

 

 

Thank you so much for helping me out by taking your time.

You're amazing Rodrigo.

 

Link to comment
Share on other sites

Hi,

 

That particular line is quite simple actually. When you create a GSAP instance, by default it's moving forward and of course it starts at 0 seconds. Adding a reverse() method after instantiating the timeline basically tells the timeline: "go backwards", so the timeline starts reversing until it reaches the start position. Since at that stage of the code we haven't added a single instance to the timeline and considering that at most, the time elapsed between the timeline being created and the reverse() method is 1 or 2 milliseconds (virtually nothing), the timeline is created, is at 0 seconds and going backwards. Then we add the instances to the timeline and then we control it using the reversed() method, which is basically a shorthand for using an if else block to use either play() or reverse(). Since the state property that toggles the timeline is found in the component's global scope is a very handy solution.

 

I hope it makes sense.

 

Happy Tweening!!!

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