Sacha Posted December 7, 2021 Share Posted December 7, 2021 Hello, first thank you for this amazing and powerful toolset! You're doing an amazing job and helping a lot of people. I'm using GSAP scrolltrigger on my React Gatsby page. One of the uses is setting the background color of my navigation bar to a different color, when scrolled past specific sections. This all works great. Because of the rooting system of a react app, the triggers and timelines don't get killed automatically when a page is changed. So I have to kill them manually. Yesterday it worked if the scrolltrigger wasn't active. So if I changed pages without activating a scrollTrigger, they would get killed, otherwise if they were active, the wouldn't. Now it somehow doesn't kill anything anymore at all. Also I'm having a really weird bug when setting markers to "true". When "false", everything is fine, but on "true", the site is buggy and creates markers on the bottom of the page and adds a second scrollbar and everything. Really weird behaviour. But that shouldn't be the focus of this post. I tried setting up a codepen, but couldn't figure out how to import React.. Maybe someone can give me a quick tip to set one up, so I could try to replicate the behaviour there. Here's the code I'm using if that helps. useEffect(() => { gsap.set(navRef.current, { backgroundColor: "rgb(255, 255 255)", }); let gsapNav = []; // nav background color adapt to section color gsap.utils.toArray(sectionRef.current).forEach((section, i) => { let bgcolor = section.current.dataset.bgcolor; gsapNav[i] = gsap.to(navRef.current, { scrollTrigger: { markers: false, trigger: section.current, start: "top 102px", end: "bottom 102px", toggleActions: "play reverse play reverse", }, backgroundColor: `rgb(${bgcolor})`, duration: 0.3, }) }); // cleanup function when page is changed return () => { // prints both scrolltriggers console.log(gsapNav); gsap.utils.toArray(sectionRef.current).forEach((section, i) => { gsapNav[i].kill(); console.log("kill " + i) }) // still prints both scrolltriggers / tweens console.log(gsapNav); } }, []); And here the JSX () return ( <section> <div>Some content</div> </section> <section ref={sectionRef.current[0]} data-bgcolor="239, 244, 248"> <div>Some content and color change</div> </section> <section> <div>Some content</div> </section> <section ref={sectionRef.current[1]} data-bgcolor="239, 244, 248"> <div>Some content and color change</div> </section> ) Link to comment Share on other sites More sharing options...
Cassie Posted December 7, 2021 Share Posted December 7, 2021 Hey there Sacha, welcome to the GSAP forums! You can use codesandbox to put together a demo. Here's a starter template -https://codesandbox.io/s/gsap-react-starter-ut42t I would suggest using useLayoutEffect as scrollTrigger needs to do layout calculations.https://kentcdodds.com/blog/useeffect-vs-uselayouteffect Also, have you checked out our react articles? Link to comment Share on other sites More sharing options...
Sacha Posted December 7, 2021 Author Share Posted December 7, 2021 Hey Cassie, first thank you for the additional links! The article states we should use refs to define timelines, so they wont get rerendered every time. That's something I didn't do yet, maybe it fixes my problem. Is this only the case for animations / timelines that are used on multiple pages or also for a scrollTrigger animation that I only run on my index page? EDIT I used this approach for my problematic code, and it didn't resolve it. Now it's back to working when no scrolltrigger was activated, and breaking when some trigger was activated.. I will try to reproduce it in a sandbox. Link to comment Share on other sites More sharing options...
OSUblake Posted December 7, 2021 Share Posted December 7, 2021 1 hour ago, Sacha said: The article states we should use refs to define timelines, so they wont get rerendered every time. That's something I didn't do yet, maybe it fixes my problem. Is this only the case for animations / timelines that are used on multiple pages or also for a scrollTrigger animation that I only run on my index page? Putting a timeline in a ref is only for when you need to access that timeline outside of an effect. But a making a minimal demo on CodeSandbox will help with troubleshooting your issue. Link to comment Share on other sites More sharing options...
Sacha Posted December 7, 2021 Author Share Posted December 7, 2021 I tried my best recreating it in a sandbox. Here also I'm not able to kill the scroll trigger and it's still active on the second page. I can't recreate the bug with the multiple scrollbars, but I guess it will be fixed together with the other problem. https://codesandbox.io/s/react-router-link-example-forked-11glv Link to comment Share on other sites More sharing options...
OSUblake Posted December 7, 2021 Share Posted December 7, 2021 How do listen for route changes? I think you need to kill your ScrollTriggers when that happens, but I'm not super familiar with react router. onRouteChange() { ScrollTrigger.getAll().forEach(t => t.kill()); } Link to comment Share on other sites More sharing options...
Sacha Posted December 7, 2021 Author Share Posted December 7, 2021 In React you can do cleanup functions after the useEffect. So like I did in the sandbox. If you look at the console, you see that the console logs are being fired, but the tweens are not being killed. useEffect(() => { //code //cleanup return () => { console.log(gsapNav); gsap.utils.toArray(sectionRef.current).forEach((section, i) => { gsapNav[i].kill(); console.log("kill " + i); }); console.log(gsapNav); }; }, []); And the bug did actually replicate just like on my page. If you don't scroll to the first scrolltrigger and click on the link, the scrolltrigger doesn't appear on the second page. But if you scroll to the blue section and trigger the scrolltrigger and click on the link, the markers are still visible on the second page and it creates blank scrollable content. Link to comment Share on other sites More sharing options...
OSUblake Posted December 7, 2021 Share Posted December 7, 2021 I know about the cleanup function, but it fires too late. I think need to kill the ScrollTriggers when the route changes, and not when the cleanup functions fires. But again, I don't know how to do that in react router. And your console log statement just shows the instances, not whether or not it has been killed, so it will always show 2 tweens. Another option, just refresh ScrollTrigger after the page changes... assuming you killed your ScrollTriggers in the other page. function Page2(props) { const id = props.match.params.id; useEffect(() => { ScrollTrigger.refresh(); }, []) return ( <div className="page page2"> <h1>Page 2</h1> <p>Sent id: {id}</p> </div> ); } 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