Jump to content
Search Community

1. Optimizing Scrolltrigger and Gsap on multiple React instances. 2. Position issue when state changes

jjtoikka test
Moderator Tag

Recommended Posts

Hello all ? and thanks for a great library!

 

I have a complex gsap setup with scrolltrigger in use. I have buit a custom animation library with these tools, so I'm creating a lot of timelines and scrolltriggers. I use useLayoutEffect inside a custom hook, I'll kill the timeline in the cb. My components have a parentAnimation components which  can create timelines and childAnimation components which receives those through React context

1. I have to use these react components separately on our CMS setup, cos each of those are rendered on different roots (don't ask why :)). So all of the react instances have probably their own scrolltrigger and gsap setups? How I can optimize that. Like, can I set the gsap and scrolltrigger to the window object or similar, so it can be shared on different react instances, so there wouldn't be any duplicates?

 

2. If I use parentAnimation and pass there inside childAnimations as children, those animations will be stacked on the parent timeline nicely.  If one of the children has state the animation goes to the end of the timeline, because it's rendered afterwards. If I want to have that instance on timeline first, what's the best way to do it? Currently I set the position to 0 on that component, and shift others by one, but this is not a good approach, like if there are delays etc. on the animations.

 

Thanks, Janne



 

Link to comment
Share on other sites

Hi Janne and welcome to the GreenSock forums!

 

First recommendation would be to use GSAP Context in your React setup, for better cleanup, scoping and other perks it has:

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

 

7 hours ago, jjtoikka said:

So all of the react instances have probably their own scrolltrigger and gsap setups? How I can optimize that. Like, can I set the gsap and scrolltrigger to the window object or similar, so it can be shared on different react instances, so there wouldn't be any duplicates?

I'm not sure I completely follow your intentions here. You mean you create different GSAP and ScrollTrigger instances on each component like this:

const myComponent = () => {
  useLayoutEffect(() => {
    const t = gsap.to(/*...*/);
    const st = ScrollTrigger.create({/*...*/});
  }, []);
};

Or are you talking about a general/global object that contains a reference to each GSAP instance? I would probably trust each component's GSAP Context instance for that or create a React Context that wraps the app and has access to all the instances. But as I mentioned I'd try to go the route of using GSAP Context for that. Also don't even mention using the window object to React purist, they could have a stroke or put you in jail for that ;)

giphy.gif

 

 

In terms of moving timeline child instances perhaps shiftChildren() would be the best option:

https://greensock.com/docs/v3/GSAP/Timeline/shiftChildren()

 

If you keep having issues, it's always a good idea to create a minimal demo that clearly shows the problems you're having.

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hi @Rodrigo and thanks for the swift answer.

 

Is this the right way to use the context? This is my hook for using the animations.

 

import { gsap } from 'gsap';
import { useLayoutEffect, useRef } from 'react';

import { AnimationProps } from '../types/index.js';

export default function useAnimation(
  timeline: gsap.core.Timeline,
  animationProps?: AnimationProps
) {
  const animatedElem = useRef<HTMLDivElement>(null);

  useLayoutEffect(() => {

    const ctx = gsap.context(() => {
      const target = animationProps.target || animatedElem.current;

      const toProps = {
        ...animationProps.to,
        ...(animationProps.scrollProps && {
          scrollTrigger: {
            trigger: animatedElem.current,
            scrub: 1,
            start: 'top top',
            ...animationProps.scrollProps,
          },
        }),
        ...(!animationProps.to && { duration: 0 }),
      };

      const tween = gsap.fromTo(target, animationProps.from || {}, toProps);

      timeline
        .addLabel(animationProps.label || 'element')
        .add(tween, animationProps.position);
      if (animationProps.shift)
        timeline.shiftChildren(animationProps.shift, true);
      
    });

    return () => ctx.revert();
  }, []);

  return [animatedElem];
}

 

Tried the shifting, but I guess it only shift forward and I need to send the animation to the start, so I guess it doesn't help?

 

Yep, I know that window object and React is not the way to do it. It's a horrible solution, so I guess it doesn't matter, if there are multiple instances in the html page.

 

Minimal demo is very hard to setup, cos there are so many different things around it. Everything is in npm component library, and then I'm using those in Hubpot. Hubspot renders the component as javascript to the certain place on the html. Here I'm currently using it https://www-solein-com.sandbox.hs-sites.com/en/ if that helps.

 

Cheers, Janne

 

 

 

 

 

Link to comment
Share on other sites

Hi,

 

11 hours ago, jjtoikka said:

Yep, I know that window object and React is not the way to do it. It's a horrible solution, so I guess it doesn't matter, if there are multiple instances in the html page.

Well another thing you should consider in this case is when using SSR. If someone uses your package in a Next app, you could run into problems if the code runs on the server, but that safeguard is super simple. Also for those cases this hook could be useful as well:

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

 

Regarding the code you posted, yeah I don't see any issues with it. If it's working as expected and you're not running into any issues, then it means it works right? ;) If it ain't broken don't fix it, is what's normally said in this cases.

 

Happy Tweening!

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