Jump to content
Search Community

Next.js 13 Layout Gsap

SImonR82 test
Moderator Tag

Recommended Posts

hello guys, a quick question, I'm using Next.js 13, I'm using the native layout.js in which I've just added a Header and Footer component, so far nothing exceptional, I have my Header component in which I have a simple animation made with Gsap (useEffect). Everything seems to be working well, but the animation only works when the page is reloaded, not when I go from page to page (although that's not what I want) but, for example, after my preloader is played, no animation.
If I take my Header component out of Layout.js and put it on my home page, the animation works normally.
An idea of what I could do, the solution resists me. Thanks in advance

Capture d’écran 2023-05-26 à 16.08.49.png

Capture d’écran 2023-05-26 à 16.06.17.png

Link to comment
Share on other sites

Hi @SImonR82 and welcome to the GreenSock forums!

 

It's really hard for us to troubleshoot an issue without a minimal demo, but this might stem from the fact that you're not properly cleaning up in your effect hook. From version 18 React has strict mode which runs the effect hooks (useEffect and useLayoutEffect) twice which creates a very unique problem with from instances as explained here:

That's why we have GSAP Context now:

https://greensock.com/docs/v3/GSAP/gsap.context()

 

So your effect hook should look like this:

useEffect(() => {
  const ctx = gsap.context(() => {
    // All your GSAP instances in here
  }, scope);
  return () => ctx.revert(); // <- Super easy cleanup
}, []);

Also we always recommend using the useLayoutEffect, especially if you plan on using ScrollTrigger and/or Flip plugins. In the case of Next you can use this approach:

https://greensock.com/react-advanced#useIsomorphicLayoutEffect

 

Finally I recommend you to take a look at the resources in this page:

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Good evening @Rodrigo,
thank you for your quick reply, mine is a little less so with the kids hopping around me. Thanks for your sound advices, even without minimal demo ; ) (next time), I'm going to apply them to all my components that have an animation with gsap.
 

After a bit of digging, I realized that my animation worked as expected except that it was behind my preloader, which is managed on my page.js (Home component) or my layout is called from the beginning, so the animation is played behind the preloader then when it finishes the header and footer are already there and it's my home that arrives which is in the children of my body in the layout.
 

Basically, I'd have to call my preloader in my layout.js but that would mean giving it a 'use client' and losing the server rendering, so I don't really see the point.
 

Or I could put a time delay for my preloader on my gsap animation in the Header component.

I don't know which would be the best method.
 

Thanks in advance
Have a nice weekend

Best regards
 

home_component.jpg

Link to comment
Share on other sites

Hi,

 

Once again, without a minimal demo there is not a lot we can do. I don't know the difference between running a code with a use client or not. I'm not really aware of this particular flag. If you ask me React and Next have only complicated things even further in their latest versions with the server components, use client, app folder and such things. I worked on many Next projects when none of that nonsense was available and things were rendered in the server. Honestly it's like their looking for ways to complicate things as much as possible and make the lives of developers miserable 🤷‍♂️

 

If you have a preloader what you could do is create a global context and trigger a state property in that context once that animation is complete. Then in your components have an effect hook that has that particular state property as it's only dependency and create your GSAP instances only when that property indicates that the preloader animation is complete. Something like this:

useLayoutEffect(() => {
  if(!loaderComplete) return;
  const ctx = gsap.context(() => {}, scope);
  return () => ctx.revert();
}, [loaderComplete]);

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hi @Rodrigo
I hope you're well, thank you for your feedback, yes it's the complicated method that keeps changing to 'simplify' our lives. At least it keeps us in shape for our duty as developers to constantly evolve ; )
I'll test your tips this weekend and see if I can optimize my code.
I'll do a minimal demo next time, I promise.
Thanks again
Have a nice weekend

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