jlmakes / scrollreveal

Animate elements as they scroll into view.
https://scrollrevealjs.org/
22.35k stars 2.26k forks source link

ScrollReveal v4 beta and React Font Awesome #371

Closed kppf closed 7 years ago

kppf commented 7 years ago

Hi,

I've installed scrollreveal v4-beta14 using yarn add scrollReveal@beta to an Isomorphic React app (A fork of https://github.com/kriasoft/react-starter-kit ). I'm using it to animate FontAwesome Icons (Similar to At your service section of https://blackrockdigital.github.io/startbootstrap-creative/ ).

It is working properly if I'm using normal element like

<i
    className={`fa fa-4x fa-${this.props.icon} sr-icons`}
    ref={icon => {
        this.icon = icon;
    }}
/>

But if I use it with react-fontawesome library (https://github.com/danawoodman/react-fontawesome), then it's not working. The icons just show, without any animation.

<FontAwesome
    className="sr-icons"
    name={this.props.icon}
    size="4x"
    ref={icon => {
        this.icon = icon;
    }}
/>

The JS used it -

componentDidMount = () => {

    const config = {
      origin: 'right',
      duration: 600,
      delay: 200,
      distance: '0px',
      scale: 0.3,
      easing: 'ease',
    };

    ScrollReveal().reveal(this.icon, config);
  };

Kindly help to get it working with react-fontawesome library. The case is same with any Custom Component - Not working. So not an issue of react-fontawesome library probably.

Secondly, not so important, how to reveal the elements one by one as in the sample link above?

jlmakes commented 7 years ago

Have you inspected what this.icon actually is?

The reference you’re storing is the <FontAwesome/> component, not the icon’s HTML element (like in your first example). So to put this another way, you’re basically doing this:

ScrollReveal().reveal(<FontAwesome/>, config)

ScrollReveal does not understand React components as reveal targets. I recommend trying to get access to the underlying HTML element—perhaps something like this:

componentDidMount = () => {
    const config = { ... }
    const target = ReactDOM.findDOMNode(this.icon)
    ScrollReveal().reveal(target, config)
}

Here is a working example.

Secondly, not so important, how to reveal the elements one by one as in the sample link above?

The documentation covers how to sequence animation.

kppf commented 7 years ago

Thanks @jlmakes, that works fine, except that I get eslint warning - Do not use findDOMNode (react/no-find-dom-node). Is there a way to avoid this warning (except by suppressing it)? Can we make a function in ScrollReveal which automatically finds the DOM node if the Component is passed to it, and animates it? I'm not sure of it's usability and feasibility though.

Animation sequence requires to pass a class selector (.box in the example in documentation). In React, we have reference and not class selector, so do we need to pass multiple references? If yes, how exactly? Or what other way it can be done?

jlmakes commented 7 years ago

Thanks that works fine, except that I get eslint warning - Do not use findDOMNode (react/no-find-dom-node). Is there a way to avoid this warning (except by suppressing it)?

The official documentation recommends against it, because you’re not supposed to manipulate the DOM directly with React—you’re supposed to change the state and let React re-render the DOM.

However, at one point, the documentation mentioned that integrating with 3rd party libraries (that require access to DOM nodes) was one of the use cases where it was “okay” to use findDOMNode(). It looks like they removed this bit, but your situation with ScrollReveal is a perfect example of this.

The reality is that these guidelines (and your ESLint rules) are there to help you make good decisions, and as long as you know you should not make a habit of accessing/modifying DOM nodes within React—you can decide to break the rules when it suits the situation.

Can we make a function in ScrollReveal which automatically finds the DOM node if the Component is passed to it, and animates it? I'm not sure of it's usability and feasibility though.

You’re welcome to fork ScrollReveal, and modify your copy of the reveal() method to accept React components. However, this is not something I want to do for the main package.

Another option you could explore though, is forking react-fontawesome and adding a ref inside the render function so you could easily access the icon’s DOM node without using findDOMNode()—the source is only 100 lines of code!

A more general solution could be to create a <ScrollReveal/> component that accepts options via props, and creates reveals for its children. The world is your oyster!

Animation sequence requires to pass a class selector (.box in the example in documentation). In React, we have reference and not class selector, so do we need to pass multiple references? If yes, how exactly? Or what other way it can be done?

The reveal() method accepts:

So more than likely, you would need to pass an array of DOM nodes if you wish to create a sequenced animation. This is not really much different than what we were doing before, you can see an updated working example.

kppf commented 7 years ago

Thanks @jlmakes. I'm now able to use ScrollReveal exactly the way I wanted. Passing DOM node list worked. Thanks for the help.