Jump to content
GreenSock

flowen

Animating a styled-component in React with GSAP

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

Hi,

 

I was following this great tutorial by Rodrigo Hernando https://greensock.com/react

 

And it didn't work. I realised after a while it was because of a styled component. Now personally I have no clue why, because I'm not sure what happens under the hood. I'm sure it has something to do with the way Styled components are rendered and have no lifecycle updates or render method.

 

Does anyone think this can be fixed? or does it simply mean I cannot use styled components?

 

(I'll uplaod a codepen later if requested)

 

Link to comment
Share on other sites

Have you tried using innerRef instead of ref?

  • Like 2
Link to comment
Share on other sites

Hi,

 

Indeed you need to find a way that the creators of the components give in order to reach into the component and get the DOM node. In this case Styled Components do allow the use if innerRef as @y4ure mentions. Here is an issue on the repo about it with some sample snippet:

 

https://github.com/styled-components/styled-components/issues/1151

 

Try this and if you keep having issues, create a stackblitz or codepen sample to get a better look at the problem.

 

I remember using Ant Design for a project and ultimately we had to bake our own version of some components in order to expose the DOM nodes when needed. As mentioned before, this all depends if the creators of the libraries allow users access to the DOM nodes of their components. Some do and some don't for security reasons, but that's outside the scope of this thread. Personally I've never worked with this library, I'm an old fashion guy that writes it's own SCSS files for the styles and uses class declarations in my components, but perhaps that comes with being over 40 :D

 

Happy Tweening!!!

 

PS: thanks for the kind words about the article ;) 

  • Like 3
Link to comment
Share on other sites

@Rodrigo and @y4ure thanks! I had a look. Damn I don't like these extra layers of complexity. So it's either this, or write my top components as normal react components with CSS classes - which gives me a mix of styled components and css.... 

 

@Rodrigo I'm also quite an oldie, 35 in 2 month's ;)  Actually I've been switching to styled components since 2 days ago.

 

My experience so far started out being exciting and soon faced frustration. I tried so many hacks and looked for the perfect situation: combine SCSS w styled comps. Unfortunately, I'm not sure how to make styled components work with SCSS. Something with sass-extract plugin.. but I gave up, too many hacks and my 'wisdom' taught me that I better stay out of hackiness I don't fully understand.

 

All in all, it's a good experience. Using CSS variables now (screw IE11!) and write all my CSS in a template string and use JS objects for stuff like breakpoints (can't use css variables for this). 

 

I miss my mixins and some functions though.. I can't be bothered to rewrite my mixins to JS, there is so much overhead compared to SCSS. If you can miss your mixins and other SCSS functions, give it a try! 

 

 

 

 

 

Link to comment
Share on other sites

hm another question:

 

I have a dynamic number of array items and I want to stagger them on a Timeline (in total I have like 9 elements animating). 

 

Now I'm unsure how to store the ref dynamically to a property in the Class component (as is done in the example referred to on github)

 

What I've tried is creating an empty array and push in the node (for reference), but it always logs as empty. 

 

I'm trying the following, but perhaps what I'm trying is just not possible:

 

constructor(props) {
  super(props)
  
  this.firstName = null
  this.lastName = null
  this.herobullets = []

  this.tl = new TimelineLite({paused: true});
}

componentDidMount() {
  TweenLite.set(this.firstName, { yPercent: 150 })
  TweenLite.set(this.lastName, { yPercent: 150 })

  console.log(this.herobullets) // logs empty
  this.tl
    .to(this.firstName, 0.5, { yPercent: 0 }, +0.7)
    .to(this.lastName, 0.5, { yPercent: 0 })
  // .staggerFromTo(this.herobullets, 0.5, {yPercent: 20}, 0.25)<-- doesnt work obviously
    .play();
  // first and last name animate perfectly
}


render() {
  <FirstName _ref={node => (this.firstName = node)}>First name</FirstName> 
  <SurName _ref={node => (this.lastName = node)}>Last name</SurName>
  <HeroList>
    { this.props.heroList.map((text, i) => {
     return (
      <li className="overflow" key={`${i} + li`}>
          <HeroBullet className="herobullet" _ref={node => this.herobullets.push(node)} key={i}>
          {text}
          </HeroBullet>
      </li>
      )
      }) 
  }
  </HeroList>
}

 

Link to comment
Share on other sites

Hi,

 

As mentioned before this is related to whether or not you have access to the DOM node in the component you're using, and if the creators of that component, actually expose the ref to the public. This is up to each component creator and if you want you can ask them to implement that, otherwise you have to do it yourself. Read from the link including the Callback Refs part (check the second snippet in that section as well):

 

https://reactjs.org/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components

 

Here's a simple example of that particular pattern, which is the simplest way to pass a reference to the parent (when is actually needed), but as I said, this requires for you to control the component:

 

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

 

Finally an alternative (not an elegant one though) is to wrap each <HeroBullet /> in a <div> and use the ref on the div and tween those, but this could break the component's layout.

 

Happy Tweening!!

Link to comment
Share on other sites

48 minutes ago, Rodrigo said:

Hi,

 

As mentioned before this is related to whether or not you have access to the DOM node in the component you're using, and if the creators of that component, actually expose the ref to the public. This is up to each component creator and if you want you can ask them to implement that, otherwise you have to do it yourself. Read from the link including the Callback Refs part (check the second snippet in that section as well):

 

https://reactjs.org/docs/refs-and-the-dom.html#exposing-dom-refs-to-parent-components

 

Here's a simple example of that particular pattern, which is the simplest way to pass a reference to the parent (when is actually needed), but as I said, this requires for you to control the component:

 

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

 

Finally an alternative (not an elegant one though) is to wrap each <HeroBullet /> in a <div> and use the ref on the div and tween those, but this could break the component's layout.

 

Happy Tweening!!

 

Ohh, I see I made a silly newbie mistake here. For some reason I forgot that HeroBullet's ref wasn't passed through like my first question... Doh! Sorry for taking your time but thanks again for reply'ing so fast! ?

 

Link to comment
Share on other sites

No worries, happens to everyone.

 

Happy Tweening!!!

  • Like 1
Link to comment
Share on other sites

  • 11 months later...

Hello all is this something that we are talking about in this topic. I love gsap and styled components is the way to go for me in our usecase so wanted to know if this is something that can be implemented. https://www.styled-components.com/docs/advanced#refs

 

Do let me know if there are any updates to the same. That has not been covered in this document. 

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