Jump to content
GreenSock

blitz2061

TimelineMax/attrPlugin not working with React

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello - I've been working on getting attr: to work with my React app, but to no avail. I am simply trying to translate the location of an object. Using to and manually setting the x and y values works. This might have something to do with the virtual DOM, but not entirely sure. Has anyone else run into this or was successful in making this work?

 

Code for clarity, in componentDidMount():

setTimeout(() => {
  var tl = new TimelineMax()
  const right_arm = findDOMNode(this.refs.right_arm)
  tl.to(right_arm, 2, { attr:{d:"M 286,61 485,61"}}, 1)
}, 2000)

Thanks in advance!

Link to comment
Share on other sites

You can absolutely use GSAP in React. No problem at all. It's kinda tough to troubleshoot blind, though - any chance you could provide a reduced test case in codepen or something so that we can see exactly what's happening? Are you getting any errors? Is the "d" info changing at all when you watch it in Dev Tools? What version of GSAP are you using? I'd definitely make sure you're using the latest (1.19.1)

 

One guess is that your "d" string doesn't have a matching number of values. If that's the case, you'll need to use MorphSVGPlugin (a membership benefit of Club GreenSock - it allows you to morph between ANY "d" data even if the number of points varies drastically). http://greensock.com/club/

 

I'm sure you can get up and running with GSAP in React...we just need a little more info. 

 

Happy tweening!

  • Like 2
Link to comment
Share on other sites

Thanks for the response! How can I go about importing GSAP into Codepen?

Link to comment
Share on other sites

There's a super-easy way to do it. Just open the pen settings, and in the JavaScript area, there's a "Quick-add" dropdown that has GreenSock TweenMax in it. Or you can copy the CDN URLs from our download overlay

gsap-in-codepen.png

  • Like 1
Link to comment
Share on other sites

Thanks for the quick responses! Top of the line support - especially for a non-customer (may become one soon!),

See the Pen EmwjGy by anon (@anon) on CodePen

See the Pen EmwjGy by anon (@anon) on CodePen

See the Pen EmwjGy by anon (@anon) on CodePen

I am not using FindDOMNode to target the refs, but rather locating the SVG elements based on the ID. I didn't know how to bring FindDOMNode into codepen (would love to learn!).

 

It works absolutely fine here, but fails to work in my application.

See the Pen ybzYva by anon (@anon) on CodePen

(stripping out a lot of unnecessary elements). Not working, just a copy paste job.

 

Ultimately, I would like to accomplish two things:

 

1) Get the animations working

2) Use FindDOMNode to target the refs.

 

Let me know of any questions!

 

Link to comment
Share on other sites

Also: My console error code is: 

 

bundle.js:43 Uncaught Cannot tween a null target

Link to comment
Share on other sites

One more file - 

See the Pen aWLdva by anon (@anon) on CodePen

 

This is using FindDOMNodes - and I receive no error message - but animation does not work. 

Link to comment
Share on other sites

Since I'm not a React guy, I can't offer much help with the findDOMNodes thing, and your example codepen was completely non-functional (looks like you literally just pasted in ES6 code to the JS panel and left everything else blank), but here's a quick fork that shows x and fill animating: 

https://codepen.io/GreenSock/pen/a9b521fc21c068c3affa71f81cb92eff/?editors=1010

 

One thing to note is that if you're going to tween an attribute ("fill" in this case), it must actually be present and populated on the element. Otherwise, GSAP has no idea what value it's tweening FROM. 

 

Does this help at all? 

  • Like 1
Link to comment
Share on other sites

Hey Jack - 

 

Thanks for the feedback. I've done a lot of research, and learned a bunch through the process - but the attrPlugin still is not working on my end, all things held equal between the Codepen and the React app itself. Perhaps this is an issue with the node module?

Link to comment
Share on other sites

It might help to verify...

 

Right before your tween, can you console.log() the element's attribute value at that point? Is it valid? For example:

var target = findDOMNode(this.refs.right_basket);
console.log(target.getAttribute("fill")); //is this reporting a color? 
TweenMax.to(target, 2, {attr:{fill:"red"}});

And you're loading TweenMax, right? That has AttrPlugin inside of it, but if you're only loading TweenLite and TimelineLite, for example, it wouldn't be able to tween attributes because AttrPlugin isn't loaded. I'm totally guessing here :)

Link to comment
Share on other sites

Hi,

 

I was passing by to se the new features in the forums and ran into this post and I thought I'd offer some tips about using GSAP and React.

 

First the following is a big NO-NO:

On 2017-5-4 at 3:33 PM, blitz2061 said:

I am not using FindDOMNode to target the refs, but rather locating the SVG elements based on the ID. I didn't know how to bring FindDOMNode into codepen (would love to learn!).

Never use regular selectors while working with React. This because the component could get an update later and re-render. In this case the id(s) could change or even a DOM node with a specific ID could not be render again, then you get the can't tween a null target error. This goes to master Doyle as well, but we'll forgive his sins because He has given us GSAP :-D. To get a specific element just use this.refs, that points to the node being rendered in the DOM.

 

Second, you added almost 300 lines of SVG code on the component's render method, try to avoid this in order to keep your components small, clean, easy to read/debug/maintain and reusable, which are the cornerstone of component-based development, not only with React, but also with Angular2/4+, Vue, etc. If you can break your svg into smaller component it'll be very easy, remember: "Divide and Conquer" ;)

 

Finally is not necessary to use the bracket notation on JSX. Keep in mind that the component's reference is an object, so you can pass an string to it and React will look for that ref attribute on the code and pass whatever string to the object:

 

render(){
  return <div ref="myDiv"></div>;
}

// Then React does this (this is very simplified of course
component.refs["myDiv"] = nodeObject;

// So you can access your node
this.refs.myDiv;

 

So a real GSAP code could be like this:

 

componentDidMount(){
  const target = this.refs.targetGroup;
  TweenLite.to(target, 1, {});
}

render(){
  return(
    <svg xmlns="http://www.w3.org/2000/svg" id="svg2" version="1.1" viewBox="0 -10 573 367" height="367px" width="573px">
    	<g ref='targetGroup'>
    	// svg code or component here
    	</g>
    </svg>
  );
}

 

As for the attribute plugin part, Jack has that already working so no need to go into that.

 

Happy Tweening!!

  • Like 5
Link to comment
Share on other sites

Thanks for your help, Rodrigo!

Stick around and defend your position on the leader board:)

 

Hope all is well!

 

Carl

 

 

  • Like 2
Link to comment
Share on other sites

Thanks for the clarification, Rodrigo. I'm curious - is there a "React way" to grab multiple elements? For example, "refs" sounds like basically "id" in the DOM, but what if someone has 25 list elements that they want to feed into a staggerTo()? In the non-React world, you could simply apply a class to each and target ".myClass", but how would you do that in React? It'd kinda suck if you had to do [this.refs.e1, this.refs.e2, this.refs.e3, ...] 

  • Like 1
Link to comment
Share on other sites

For a better understanding of React, please see this post. In a nutshell, React is nothing more than a recursive call to document.createElement("someElement");

 

 

  • Like 2
Link to comment
Share on other sites

2 hours ago, OSUblake said:

React is nothing more than a recursive call to document.createElement("someElement");

 

Bingo!!!, that's the key to understand it. As always @OSUblake has the nail locked and He hits it in the head!!! :-D

 

7 hours ago, GreenSock said:

I'm curious - is there a "React way" to grab multiple eleme

 

@GreenSock, well, this is kind of tricky. First when working with React data is normally passed either as a JSON file or in object notation. So normally elements that share something in common (such as a specific class) are stored in arrays:

 

const els = [
  {name: "Jack", ocupation:"Master of GSAP"},
  {name: "Carl", ocupation:"Geek Ambassador"},
  {name: "Blake", ocupation:"Superstar Moderator and JS wikipedia"},
  {name: "Jonathan", ocupation:"Superstar Moderator and Browser-Quirks reference"},
  {name: "PointC", ocupation:"Superstar Moderator and SVG Mastermind"}
];

 

When adding this to the virtual DOM you can use the map array helper:

 

render(){
  <div className="staff-wrapper">
    {els.map((element, index)=>{
      return <div className="staff-card" ref={element.name}></div>;
    });}
  </div>
}

 

Now when it come to select them all, normally we use querySelectorAll or getElementsByClassName. I'm not very familiar with the specs of this methods, but I can assume that they involve some traversing the DOM tree looking for elements that match the argument. In this case we're setting the ref name for every element by hand, so we have full control over that aspect of our code, so we can loop trough our collection again, matching the ref name using a for or forEach loop, or even using the map method to get a new array:

 

// to create a single animation for each element
els.forEach((e,i)=>{
  TweenLite.to(e, 1, {rotation:360});
});

// to create a stagger animation
const targets = els.map((e,i)=>{
  this.refs[e.name];
});

TweenMax.staggerTo(targets, 1, {rotation:360}, 0.1);

 

Here are a couple of samples of a marquee I made for a React app using the modifiers plugin, this is just a simple prototype because I'm bound by some silly NDA for the complete code :mellow:.

 

This is just React and CSS:

See the Pen a8c4bf4d6ddaf17165e7dded0b5f4b0d by rhernando (@rhernando) on CodePen

 

And this uses PIXI, just an experiment to see if there was a better performance, since the real thing uses images and text:

See the Pen qmVXOK by rhernando (@rhernando) on CodePen

Well, that's about it, hopefully this helps to make things clear about this and other questions regarding React.

 

Last but not least, @Carl, thanks buddy, is always a pleasure to come back home. Things are going pretty well, still not having a lot of free time but hopefully at some point I'll be back full-time. It certainly feels good when I post an answer or a thread and everyone welcomes me, I feel like Norm in Cheers 8-)

 

Happy Tweening!!!

  • Like 2
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.
×