Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
madleo

Targeting/Animating DOM nodes using CSS selectors VS passing elements directly

Recommended Posts

Hi Team,

 

Within the virtual DOM environment (Vue, React, etc), what's the difference between targeting/tweening an element using a ref vs selecting via css selector string (performance, known quirks/bugs)? I've been targeting/animating virtual DOM elements using css selectors, but just came across the "Getting Started: React and GSAP Animations" and see that using refs is advised. Perhaps I'm veering too far away from a GSAP specific question at this point, and if that's the case, understanding the difference between targeting with css selectors vs targeting the node/element directly would be certainly helpful. 

 

Thanks in advance!

Link to comment
Share on other sites

I'm not much of a React/Vue/framework guy so I'm not in a good position to answer this, but hopefully @Rodrigo (the author of that article) or one of the other moderators with experience in that stuff ( @Dipscom, @OSUblake ) will chime in. My suspicion is that React/Vue like to swap things out from underneath you in the virtual DOM, so they prefer that you use their own way of referencing things so that you don't have references to stuff that they nuked. I could be wrong. 

 

Either way, though, in order for GSAP to work they can't just willy-nilly swap stuff out mid-animation because those instances are referenced by GSAP. In other words, if you've got a <div id="thing"></div> and GSAP starts animating that (maybe it got the reference via a "#thing" selector) and then React is like "yeah, I'm just gonna nuke that and build another <div id="thing"></div> in its place), that ain't gonna fly. It'd be extremely inefficient too if GSAP had to keep on re-querying the DOM (or virtual DOM) to update its reference 60 times per second, you know? 

 

So it seems to me like CSS selectors probably work fine as long as your animation is starting immediately (and React/Vue aren't swapping stuff out mid-tween), but using the ref instead ensures that scheduled tweens have the best chance of using the proper element if React/Vue decided to rewrite something in the virtual DOM between when your animation code was evaluated and when it actually begins. Again, just my guess. I'm sure someone else can offer a "real" answer ;)

  • Like 4
Link to comment
Share on other sites

I think that qualifies as a "real" answer, haha. Definitely helps.

In case @Rodrigo or another React vet has a chance to assist, allow me to briefly set some small context here. In a nutshell, I'm trying to find the most efficient way of utilizing gsap within React 16.7 -- more specifically, using gsap with the newly introduced hooks such as (useEffect hook), and without the use of classes. In the mean time, when i get a chance this evening I will continue tinkering and try to incorporate refs to ensure the best chance of expected behavior.

 

 

  • Like 1
Link to comment
Share on other sites

Hi,

 

@GreenSock is right. The main concern when dealing with any type of shadow dom library/framework is what's called DOM reconciliation (something @OSUblake has more knowledge than I am). Here's what React's official docs say about reconciliation:

 

https://reactjs.org/docs/reconciliation.html

 

But back on the specific question, yeah the issue is that GSAP doesn't have the slightest idea of what could make the resulting DOM to change and as Jack mentioned is a bad idea performance-wise, so GSAP takes care of it's own end and so does React (and Vue and other shadow dom libraries as well). They work in what's called a reactive way. Something changes that makes necessary a DOM update. The good news is that all those tools offer what's normally called lifecycle methods/hooks (do not confuse with the new hooks API introduced by React) which help you do stuff, before or after the DOM is going to change as a result of a state property being mutated. That's why in every piece of documentation is highly discouraged to reach and manipulate the DOM directly, hence the usage of references (refs).

 

The only thing you have to be careful about is that if an animation is running a somehow your DOM could change and remove the tween target, be sure to kill those animations in order to prevent an error being thrown. Here is where the lifecycle methods are handy because you can use them to create the animations once the DOM has been updated and you can be sure that the elements you want to animate are present and you wont get an error or unwanted behaviour, and that you will be able to act before those elements are removed.

 

As you mention, seems that you've been selecting elements after those elements are rendered, so they are there and as you can see, since that's just good ol' plain javascript, it works. But is safer and more appropriate to follow each library's guides and patterns to do so.

 

Finally, I've check some things about React hooks but I haven't mix them with GSAP for two reasons. First, I haven't had enough time. Two, keep in mind that hooks are on the roadmap of version 17 of React, they are still a proposal and the React team is gathering information, bugs and opinions from the community as well as doing their own tests, so thechance that the API could have some major differences from what it is now is not small, so I try to stay away from using them in any type of production code. Also I don't like to invest a lot of time in things that are not even in beta or at least release candidate (RC version), because of changes in the future. But as you mention the effect hook is an easier way of triggering something because a state change. Hooks are very nice and a great addition to React and most devs I've shared some thoughts on them, are very in to hooks (they are hooked :D), so they are here to stay most likely, but changes in their API will be inevitable moving toward a stable release. I'll see if I can whip something using hooks, but you caught me in a couple of bad days, so perhaps tomorrow night or Friday I could get into that. In the mean time feel free to continue the discussion here or if you want you can PM me.

 

Happy Tweening!!

  • Like 4
Link to comment
Share on other sites

Awesome. Really appreciate the level of insight.
 
If I’m understanding this correctly (and allow me to summarize here) —
  • The surest way to get GSAP and React working together is to leverage lifecycle hooks, in that you’re able to control the creation/start of animations only after the DOM has rendered or completed an update to the DOM. With that in mind, we mainly use componentDidMount and componentDidUpdate respectively.
  • The most obvious reason for wanting to leverage lifecycle hooks is to prevent the situation where a tween target gets removed during an animation due to an update to the DOM.
  • Although the approach of selecting elements through css selectors ‘works’ given that I’m placing the animation logic in componentDidMount/useEffect, it is not best practice, less safe, and thus prone to unexpected/unwanted behavior.
 
Regarding React hooks — I completely agree, and understand that I’ve taken a risk in investing time into React hooks. I just couldn’t help myself. XP.
 
Lastly, I would certainly love to see your implementation with React hooks (React in general), but if you have to go out of your way for this, no worries -- if anything I can try to whip up something myself and you can have fun demolishing it. I'll have a little bit of time tonight, and more so over the weekend. But when I do come up with something I’ll be sure to PM you.
 
Thanks again!! @GreenSock @Rodrigo
  • Like 2
Link to comment
Share on other sites

On 12/12/2018 at 12:41 PM, madleo said:

Within the virtual DOM environment (Vue, React, etc), what's the difference between targeting/tweening an element using a ref vs selecting via css selector string (performance, known quirks/bugs)? I've been targeting/animating virtual DOM elements using css selectors, but just came across the "Getting Started: React and GSAP Animations" and see that using refs is advised.

 

 

You're not targeting the virtual DOM elements because you really don't have access to the virtual DOM. You're targeting real DOM elements, and you probably shouldn't being using CSS selectors.

 

The reason should be obvious regardless of what library/framework you're using. It's all about locality. Passing in a CSS selector to GSAP runs document.querySelectorAll(), so it's going to search the entire DOM for matching elements. That will cause problems if you use a component more than once, but want to animate an element inside a specific component. Using refs eliminates that problem.

  • Like 4
Link to comment
Share on other sites

57 minutes ago, OSUblake said:

You're not targeting the virtual DOM elements because you really don't have access to the virtual DOM. You're targeting real DOM elements,

 

That sounds right -- React takes a snapshot of the virtual DOM, compares with proposed updated DOM, then syncs/updates objects to the real DOM. At the end of the day we're targeting the real DOM.

 

Could you elaborate a little more regarding the problems that refs would resolve? Specifically the one's you're alluding to:

57 minutes ago, OSUblake said:

That will cause problems if you use a component more than once, but want to animate an element inside a specific component.

 

I think it might just be the way its phrased. Thanks in advance!

 

 

Link to comment
Share on other sites

14 minutes ago, madleo said:

Could you elaborate a little more regarding the problems that refs would resolve? Specifically the one's you're alluding to:

 

Here's a demo. I only want the box I click on to animate. That obviously does not happen as both boxes animate.

 

https://stackblitz.com/edit/react-hwyoaw?file=index.js

 

If you update the demo to use refs it will work correctly.

  • Like 4
Link to comment
Share on other sites

Ah, ok i see what you're saying -- thanks a lot for clarifying! 

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.
×