Share Posted July 24, 2020 Hi there, I am using ScrollTrigger a lot, its a fantastic addition! the only issue I've run into so far is cleaning up when using ScrollTrigger.matchMedia() when un-mounting in my React components. I've tried killing all ScrollTrigger instances, and killing timelines individually. simplified setup below: const buildTimeline = () => { // ... setup stuff ScrollTrigger.saveStyles([boxRef.current, mobileRef.current]); ScrollTrigger.matchMedia({ '(min-width: 720px)': () => { if (!boxRef.current) { console.log('boxRef does not exist'); } ScrollTrigger.create({ // config stuff animation: desktopTimeline.current .to( // animations ) }); }, '(max-width: 719px)': () => { if (!mobileRef.current) { console.log('mobileRef does not exist'); } ScrollTrigger.create({ // config stuff animation: mobileTimeline.current .to( // animations ) }); }, }); } useEffect(() => { if (!hasMounted.current) { hasMounted.current = true; buildTimeline(); } return () => { // kill all ScrollTrigger[s] ScrollTrigger.getAll().forEach(t => t.kill()); // try killing individual timelines also mobileTimeline.current.kill(); desktopTimeline.current.kill(); } }, []); This would normally work ok on ScrollTrigger instances generally - or at least it seems to! - but if I'm using matchMedia I'll still get media query change events firing where the component is unmounted (i.e. navigating to a different route). any idea what I'm missing here? Link to comment Share on other sites More sharing options...
Share Posted July 24, 2020 Hey ueno. So you're wanting to disable/kill the matchMedia when the component is unmounted? Can you just kill off ScrollTrigger completely? ScrollTrigger.kill() A minimal demo would likely be helpful in us understanding the usage. Link to comment Share on other sites More sharing options...
Author Share Posted July 24, 2020 thanks for the reply Zach It's a kind of difficult issue to do a codepen for as it is on unmount after a route change. I can probably whip up something if its unclear as to what I mean but basically using any of the .kill() methods mentioned - and ScrollTrigger.kill() - doesn't remove ScrollTrigger -- the events are still firing on resize at the defined media queries (in the code posted, <720 & >720) even though that component is unmounted and I have attempted to kill the instance in the ways I have outlined above. I can send you a DM to a demo if that would help? Thanks again for getting back to me, I appreciate it! Link to comment Share on other sites More sharing options...
Share Posted July 24, 2020 3 minutes ago, ueno said: and ScrollTrigger.kill() - doesn't remove ScrollTrigger Are you sure that the method is being called? ScrollTrigger.kill() should completely kill off all of ScrollTrigger, I'd be very surprised if events are still firing afterwards. Keep in mind that the static .kill() method is different than the instance .kill() method. Link to comment Share on other sites More sharing options...
Author Share Posted July 24, 2020 Hey there Zach, if i attempt to kill with ScrollTrigger.kill() on unmount, I get the following ts error:The 'this' context of type 'ScrollTrigger' is not assignable to method's 'this' of type 'PluginScope'. Type 'ScrollTrigger' is missing the following properties from type 'PluginScope': _props, _pt, add Is there a different way I should be calling this other than one of these methods?: import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'; useEffect(() => { // call function to setup ScrollTigger; return () => { ScrollTrigger.getAll().forEach(t => t.kill()); // no error but media query events still fire after unmount ScrollTrigger.kill(); // error, resize mq events still fire on unmount specificTimelineName.kill(); // no error but events still fire on unmount } }, []); Link to comment Share on other sites More sharing options...
Share Posted July 24, 2020 Make sure you're registering ScrollTrigger. But I don't know why that error would be happening. Please try to make a minimal demo that we can check out as given the information I'm not sure if we can help further. Link to comment Share on other sites More sharing options...
Author Share Posted July 24, 2020 I am registering it at the _app level (its a next.js app). I can't really post it here but I can send you a link to a simple demo and the source repo as a DM? I would of course post any solution as a result back into the forum. Link to comment Share on other sites More sharing options...
Share Posted July 24, 2020 Make sure you're waiting to register (and use) the plugin until the window, document, and <body> exist. It would be MUCH better if you create a minimal demo rather than just linking us to your actual project. There's usually a lot of extraneous, unrelated code and/or other complexities that may be interfering in your real project. When you create a reduced test case, it often reveals the issue pretty quickly. 1 Link to comment Share on other sites More sharing options...
Author Share Posted July 24, 2020 I am registering it correctly I'll whip up a pen as soon as i can tomorrow. Let me know if I can send you a link in the meantime? it's as minimal an example as you could imagine - its the "hello world" of matchMedia Link to comment Share on other sites More sharing options...
Share Posted July 24, 2020 Sure, feel free to shoot me and/or Zach a DM. 1 Link to comment Share on other sites More sharing options...
Share Posted July 25, 2020 Got the demo. I think I see the misunderstanding. It sounds like you thought that killing a ScrollTrigger that was created inside of one of the .matchMedia() functions would somehow prevent that .matchMedia() function from ever being called again, but that's not how it works. Those are totally separate concepts. Once you set up a matchMedia() at a breakpoint, it will always get called. So the solution with your project would be to just set a variable that you can check inside that function, sorta like: let killed; ScrollTrigger.matchMedia({ '(min-width: 720px)': () => { if (!killed) { // ONLY IF NOT KILLED! ScrollTrigger.create(...); } } }); useEffect(() => { ... return () => { ScrollTrigger.getAll().forEach(t => t.kill()); killed = true; }; }, []); Does that clear things up? 2 Link to comment Share on other sites More sharing options...
Author Share Posted July 25, 2020 hey Jack & Zach, Thanks for the assistance. Yep, I assumed that ScrollTrigger.getAll() would kill everything including ScrollTrigger.matchMedia() so I misunderstood the purpose of .kill(); thanks for clearing that up A boolean flag works just fine on unmount, along with killing all the individual ScrollTriggers with a loop over ScrollTrigger.getAll() just like in your example. appreciate the clarification and thanks again for your time! 1 Link to comment Share on other sites More sharing options...
Share Posted March 18 On 7/25/2020 at 7:24 AM, GreenSock said: let killed; ScrollTrigger.matchMedia({ '(min-width: 720px)': () => { if (!killed) { // ONLY IF NOT KILLED! ScrollTrigger.create(...); } } }); useEffect(() => { ... return () => { ScrollTrigger.getAll().forEach(t => t.kill()); killed = true; }; }, []); Hi everyone tried this approach but on mounting again the killed variable value will reset hence the condition will still fire, we somehow need to have a method to kill the matchMedia on unmount, it also cause another issue when remounting back because the previous matchMedia still exist and the scrolltrigger and tweens comes with it is already been destroyed and it throws me an error "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'." this error will also show when the component has been unmounted and the screen size updated Link to comment Share on other sites More sharing options...
Share Posted March 18 Hi chacra, There is now a clearMatchMedia method. 😉 https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.clearMatchMedia() 3 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now