Jump to content


  • Posts

  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

gaearon's Achievements

  • One Month Later
  • Week One Done
  • First Post Rare

Recent Badges



  1. I wanted to note we've started adding some documentation about the mindset with which to approach these issues: https://beta.reactjs.org/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development https://beta.reactjs.org/learn/synchronizing-with-effects#triggering-animations This doesn't specifically mention GSAP and may not be particularly helpful but at least I hope this clarifies the "way of thinking" we suggest.
  2. Thanks for the extra info. I can see now why from behaves like this. I think it might be helpful to take React out of the equation and think about this similarly to a from call in a button click handler: button.addEventListener('click', () => { gsap.from(/* ... */) }) Suppose the user clicks the button twice in quick succession — without any React. Then they will have the same problem. How would you recommend them to resolve it? Whatever the recommendation is, would likely work for React effects too. (Whether it's tracking animation state with a boolean, recommending a different API than from, or something else.) From our side, we're happy to brainstorm solutions for other cases too — but it probably wouldn't be much different from this “double click” thought experiment. We don't recommend people to create "overly generic" Hooks. If it has "effect" in the name or takes dependencies as arguments, it's probably not a good candidate for a custom Hook. It's hard to suggest something more specific though because I'm not familiar with common GSAP patterns. The default behavior (without a ref) is usually the correct one. The reason we introduced it is we'd like to add a feature similar to KeepAlive in Vue that remounts a component with existing state. Like if you switch Feed -> Profile -> Feed, and we mount Feed with the previous state so that input aren't lost. To verify your components are resilient to this, we simulate unmounting and remounting with restored state right away. So this surfaces this issue. But this issue is what would happen if you were to quickly switch tabs yourself (when using our KeepAlive-like component). If you "solve" it with a ref, you're not gonna have an animation the second time at all. Or if you do it too quick it will similarly get stuck. This is why I think the proper solution is to have the effect code be resilient to double-calling. Since double-calling is exactly what would happen if we actually remount the component with previous state and DOM before the animation has finished.
  3. Hi folks! This is Dan (from React). We would generally not recommend disabling Strict Mode. It's more of a temporary workaround while the libraries are getting updated, not a permanent strategy. In general, React leans towards assuming that effects are safe to re-run extra times. Effects act like a synchronization mechanism: they let you "mirror" some state into some imperative change in the DOM. For example, an effect like this: useEffect(() => { someRef.current.style.color = myState }) would be safe to re-run at any point because it just "re-synchronizes" some information. The issue can be reproduced in vanilla JS if you call gsap.from twice: https://codepen.io/gaearon-the-encoder/pen/ZEvryNb. I don't know enough about GSAP so I can't tell whether this behavior is intentional or not. I wonder if there is some other way to call GSAP API in a way that the last call "wins" — i.e., express it as synchronization? That would resolve the issue. Alternatively, you can track whether it has already ran manually: const didAnimate = useRef(false); useEffect(() => { if (didAnimate.current) { return; } didAnimate.current = true; gsap.from(/* ... */) }, []) This would also solve the issue. (However, the "symmetrical" setup/cleanup approach in this post makes a lot of sense to me! And if the animations are truly interruptible — which is ideal — then there should not be any visible effect from double-calling at all.) If there are some particularly common patterns for using GSAP with React, it would make sense to expose them as custom Hooks with React-leaning APIs rather than using GSAP directly. This also lets you hide any quirks behind them. Please let me know if more details would be helpful! Or feel free to file an issue in the React tracker for more discussion.