Jump to content


Animation triggering on mount

Recommended Posts

I have an scrollTrigger animation created in React. In developer mode the animation works fine. But ive noticed that when switching to production mode the animation is played as the components are loaded. Giving the impression that the animation was never triggered.


I initially thought that it wasnt triggering at all in production.

I have tried various method to prevent it from triggering such as  a bool to check whether the components mounted.


I have several from animations without scrollTrigger that all work as intended regardless of development or production mode.


Perhaps someone could give me a workaround or solution to this.


Heres the relevant code:


import { useEffect } from 'react';
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
    useEffect(() => {
        gsap.from('#aboutSection', {duration: 1, y: '10%', opacity: '0', ease: 'sine', delay: '0.5', scrollTrigger: {
            trigger: "#aboutSection",
    }, []);


Link to comment
Share on other sites

I bet the problem is that React 18 runs in "strict" mode locally by default which causes your useEffect() to get called TWICE! Very annoying. It has caused a lot of headaches for a lot of people outside the GSAP community too.


.from() tweens use the CURRENT value as the destination and it renders immediately the value you set in the tween, so when it's called the first time it'd work great but if you call it twice, it ends up animating from the from value (no animation). It's not a GSAP bug - it's a logic thing.


For example, let's say el.x is 0 and you do this: 

useEffect(() => {
  // what happens if this gets called twice?
  gsap.from(el, {x: 100})
}, []);


The first time makes el.x jump immediately to 100 and start animating backwards toward the current value which is 0 (so 100 --> 0). But the second time, it would jump to 100 (same) and animate back to the current value which is now 100 (100 --> 100)!  See the issue?


So you can either turn off strict mode in React or you can add some conditional logic to your useEffect() call so that it only runs ONCE. Sorta like:

const didAnimate = useRef(false);

useEffect(() => {
  // if we already ran this once, skip!
  if (didAnimate.current) { return; }
  // otherwise, record that we're running it now and continue...
  didAnimate.current = true;
  gsap.from(el, {x: 100});
}, []);


Or you could just use .fromTo() tweens so that you define both the start and end values.


One of the React team members chimed in here if you'd like more background.


If you still need help, please make sure you provide a minimal demo (like in CodeSandbox or CodePen)

Link to comment
Share on other sites

No sorry its not strict mode.

Not only have I disabled it but it only runs in development mode.

As its a tool to literally double check errors.

I am attempting to trigger the animations in production mode, strict mode doesn't run in this mode.

Link to comment
Share on other sites

It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? 


Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.


Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen


If you're using something like React/Next/Nuxt/Gatsby or some other framework, you may find CodeSandbox easier to use. 


Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

I have tried this same mimmal demo and the same issue still occurs. As codepen and code sandbox both run development mode React .Therefore I can't be sure it works unless I'm given a demo running the production version of react and not development mode.


Heres the exact code I tried:

import  * as React from 'react';
import { useEffect, useRef } from 'react';
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
export default function About() {
    const h1 = useRef(null);
    useEffect(() => {
       gsap.from(h1.current, {
         duration: 1,
         yPercent: 10,
         opacity: 0,
         ease: "sine",
         delay: 0.5,
         scrollTrigger: {
           trigger: h1.current,
           toggleActions: "restart none none reverse"
    }, []);
    return (
        <div className="space-y-12">
            <div className="scroll-down">&darr; scroll down &darr;</div>
            <div className="h-[1500px] w-[100px] bg-red-700"></div>
            <h1 ref={h1}>It seems to work just fine.</h1>
            <p>Are we missing something?</p>
Link to comment
Share on other sites

10 hours ago, ELG0BLIN0 said:

As codepen and code sandbox both run development mode

I don't think that's true. Why do you think that? I'm definitely not a React guy, but I could only get React to run in strict mode on CodePen/CodeSandbox by explicitly forcing it with the <StrictMode></StrictMode> wrapper. 


it sure sounds like something odd with your local setup [maybe?] 


@SteveS I know you've got React experience - are you able to reproduce this at all? 

Link to comment
Share on other sites

@ELG0BLIN0 I really can't help you unless you can provide your code in a CSB / CodePen (CSB is usually better for react).

It's almost definitely an environment/ config issue and likely doesn't have anything to do with GSAP specifically. I do as much of my development in React as I can and this is not something I regularly experience.

It might be worth noting that if you enable StrictMode on the CodePen, it DOES break the example:

See the Pen zYWzymy by StevenStavrakis (@StevenStavrakis) on CodePen


So CodePen certainly doesn't enable strict mode by default.

  • Like 1
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.