Jump to content
Search Community

React/ Flip "Invalid scope" error

emmme test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hi all!

I'm trying to figuring out how to best use GSAP with react. I'm indeed unable to put the Lottie object from its starting position to inside the header next to the title. 

I already implemented a context inside a useLayoutEffect , but if i try to add an absolute:true in the Gsap.from() method i get an error "TypeError: (scope || _doc).querySelectorAll is not a function" , and without it i get "Invalid scope" alert, and the Lottie doesn't move next to the title. 

 

Here is the codesandbox https://codesandbox.io/p/sandbox/jolly-kalam-tspd3w?file=/src/pages/Home/index.jsx:38,1

Thanks in advance to anyone who wishes to help!✌️

Link to comment
Share on other sites

Hi,

 

The main issue here is that you are not doing anything that will cause an actual animation. This is more related to fact that you are missing how actually Flip works.

 

Flip takes the current state of the element, then you change something that alters the size and/or position of the element and finally you tell Flip to animate from the state you recorded to the state the element has after those changes. Here is a simple example showing that:

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

 

Then in terms of your React code is better to get the state of the element inside the GSAP Context instance and not outside. Because of the double call in effect hooks on React Strict Mode (in development) that particular state will be removed.

 

Here is a simple example of using Flip and reparenting on a React app:

https://stackblitz.com/edit/vitejs-vite-bpwfpk?file=src%2FApp.jsx

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Thank you @Rodrigo ! 

I updated the code as you suggested: https://codesandbox.io/p/sandbox/jolly-kalam-tspd3w?file=/src/pages/Home/index.jsx:21,36

I followed the steps of the FLIP acronym (inside useLayoutContext() and gsap.context() since i'm using react) :
F -> First i define the state: 

const state = Flip.getState('.flip-container');

 //btw , this produces "Invalid scope" warning in chrome dev tools, but may be related to this 

 

L -> Lastly i insert how i want the result to be: 

const container = document.querySelector(".flip-container");
const target = document.querySelector(".flip-target");
console.log(state)
setTimeout(() => {
target.appendChild(container)
}, 2000);
 
Finally , i call the Flip.from() method in order to animate the transition:
Flip.from(state, {
absolute:'.flip-container',
targets: ".flip-container",
duration: 1
})
here i call both
•the absolute property (because documentation says "This solves layout challenges with flexbox, grid, etc" )  and infact the header is inside a flex;
•the targets because documentation states this while using flip with a framework like react.
 
Still the preparenting effect is not animated by the Flip.
What am i missing ?
Link to comment
Share on other sites

I'm not a React guy, but it if you console.log(gsapApp.current), you'll see that it's undefined. So that's the problem - you're trying to define the scope as something that's undefined. The scope should either be an Element or a Ref whose .current property is an Element. That isn' the case in your demo. 

  • Like 1
Link to comment
Share on other sites

I wrapped the UI into another section which has ref={gsapApp}: That really worked in order to dismiss the "Invalid scope" warnings.

Unfortunately now the Flip.from() method interferes with the Lottie's first rendering, which gets delayed by the amount specified in Flip.from()'s duration option (1sec), and also it doesn't animate the transition from "flip-container" to "flip-target" into the header.. 🤔

Link to comment
Share on other sites

  • Solution

I noticed several problems:

  1. You've got a 3rd party library that's applying a CSS animation that's interfering. Specifically, the animate-fade-down class. 
  2. You're using a setTimeout() for some reason (typically it's better to use gsap.delayedCall()) and you didn't do proper cleanup of that timeout id. Remember that React calls the useEffect()/useLayoutEffect() TWICE in strict mode, so you're creating duplicate calls that are creating duplicate animations. 
  3. You weren't adding the Flip animation to the context. Remember that it'll only record animations that are created DURING that gsap.context()'s function invocation, but you're delaying them for 2 seconds, so they're not happening during that invocation. Just use the .add() method to add them.
  4. You're making DOM changes that affect more than just the .flip-container element. You should include the other element(s) in your Flip animation and getState() too. 

https://codesandbox.io/p/sandbox/sweet-water-h898lt?file=/src/pages/Home/index.jsx:9,33

 

I hope that helps. 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

The only time you need to use the "targets" property is when you're trying to animate (Flip) a set of targets that is different than the one in the getState() object. By default, it'll just use the same targets that had their state captured in the Flip.getState() call. So if it matches that, there's really no need to explicitly define a "targets" property. Make sense? 

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.
×
×
  • Create New...