Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My animation is not working when re rendering my react component?

So, my problem is that I have a component, I associated an animation to it and it is working when the component is rendered for the first time, but on an event click I change some conditions and some props associated to this component, But my element is not re rendered, it is just changing what has been changed, that means that the element is not removed from the dom et added to the DOM again, that's why I am not able to see the animation again, so it is not re-rendered or I just did not get what re render means.

I tried some solutions of course, but I am stuck, I tried to use this method :

this.forceUpdate();

But again, I am still not getting anything.

I dont think I have to write the whole code I wrote, becuase it is a lot and includes many other things but This is what I think is needed.

methodWillReceiveProps in my component :

  componentWillReceiveProps(props) {
    if (props.isRerendered) {
      this.forceUpdate();
    }
  }

props.isRendered is returning true everytime, I checked with some console.log methods.

This is what is rendered :

render() {
    return (
      <div
        className={cs({
          "tls-forms": true,
          "tls-forms--large": this.props.type === "S",
          "tls-forms--medium tls-forms--login": !(this.props.type === "S")
        })}
      >
      // content here 
      </div>);
 }

And here is the sass file and the simple fading animation :

.tls-forms {
  animation: formFading 3s;
  // childs properties here 
}

@keyframes formFading {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

I will really appreciate any help given.

like image 982
TaouBen Avatar asked Aug 22 '19 18:08

TaouBen


2 Answers

You could make use of keys that react is using to determine whether something has changed. This means that your render method should look something like this:

import shortid from "shortid";

getRandomKey = () => {
    return shortid.generate();
}

render() {
    return (
      <div
        key={this.getRandomKey()}
        className={cs({
          "tls-forms": true,
          "tls-forms--large": this.props.type === "S",
          "tls-forms--medium tls-forms--login": !(this.props.type === "S")
        })}
      >
      // content here 
      </div>);
 }

Since you need to run animation on each render, you'll need to generate some random key every time (that's why we are calling this.getRandomKey() on each render). You can use whatever you like for your getRandomKey implementation, though shortid is pretty good for generating unique keys.

like image 93
zhuber Avatar answered Oct 19 '22 07:10

zhuber


One way of animating a component is to attach a CSS class to it. But, when animation is done, you have to detach the CSS class so that you can re-attach when you want to animate again.

Here is a basic example:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      animateFlag: false
    };
  }

  componentDidUpdate() {
    if (this.state.animateFlag) {
      setTimeout(() => {
        this.setState({ animateFlag: false });
      }, 3000);
    }
  }

  render() {
    return (
      <div className="App">
        <button
          onClick={() =>
            this.setState({ animateFlag: !this.state.animateFlag })
          }
        >
          {this.state.animateFlag ? "Wait" : "Re-animate"} 
        </button>
        <div className={this.state.animateFlag ? "text animate" : "text"}>
          Hello CodeSandbox
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.text {
  font-size: 40px;
}

.text.animate {
  animation: formFading 3s;
}

@keyframes formFading {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Note that, I am setting animateFlag to false in ComponentDidUpdate, so that when I click the Re-animate button again, I can re-attach the animate class to the div element.

I set timeout duration to 3000ms because, the animation takes 3000ms.

like image 23
user9408899 Avatar answered Oct 19 '22 05:10

user9408899