Jump to content


React+GSAP scrollTrigger pin is faulty on v. 3.11.4 but works on 3.9.1

Go to solution Solved by GSAP Helper,

Recommended Posts

I've been having a lot of issues with the pin functionality on React. Mainly, I'm using the exact code from this CodePen, with npm install gsap@latest. (3.11.4). What it does is, when it reaches the "start" mark, it will automatically take the element and place it and the position specified first in the "end" string. For example:


start: 'top top',

end: '+=1000',


when the element reaches 'start', it will automatically go down by 1000. Which is faulty. On codepen, changing the version of the gsap package does not affect anything, it still works. in my React application, same code from codepen behaves differently on 3.11.4 vs. 3.9.1.


For now, I will keep using 3.9.1 even tho it's old. However, I think somebody might want to look into that. Hope it helps some people.





Please observe the behavior of the "Nav" element on the two gsap versions.



See the Pen LYeNwOv by tripti1410 (@tripti1410) on CodePen

Link to comment
Share on other sites

  • Solution

Hm, it's tough to troubleshoot blind but it sure sounds like you're being bitten by the React 18 double-invoke of useEffect()/useLayoutEffect(), leading to creating of duplicate/competing animations/ScrollTriggers. Don't worry, there's a very easy solution. 


First, I'd strongly recommend reading this article:


In GSAP 3.11, we introduced a new gsap.context() feature that solves all of this for you. All you need to do is wrap your code in a context call, and then return a cleanup function that reverts things: 

// typically it's best to useLayoutEffect() instead of useEffect() to have React render the initial state properly from the very start.
useLayoutEffect(() => {
  let ctx = gsap.context(() => {
    // all your GSAP animation code here
  return () => ctx.revert(); // <- cleanup!
}, []);

If you're still having trouble, would you mind providing a minimal demo that clearly shows the issue? Here's a Stackblitz starter that you can just fork: https://stackblitz.com/edit/react-cxv92j?file=src%2FApp.js


I did it myself with that CodePen you provided and it seems to work fine - am I missing something?:


Link to comment
Share on other sites

This was, indeed, the issue! What I've done now is esentially I've used the article you provided as inspiration, and before I had a useEffect without  cleanup & context, that simply said gsap.timeline( animate here etc.). Thank you for your help!


Now, the useEffect looks like this (for other who run into the same issue and need a quick fix) :



useEffect(() => {
  let ctx = gsap.context(() => {
      scrollTrigger: {
        trigger: ideRef.current,
        start: "top top",
        end: '+=1000',
        scrub: true,
        anticipatePin: 1,
        markers: true,
  }, headerRef)
  return () => ctx.revert();
 }, [])
  • Like 4
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.