Quuxuu
Quuxuu

Reputation: 679

How to trigger a CSS animation on EVERY TIME a react component re-renders

I want to play an animation on a react component every time it rerenders due to prop change:

react:

function Card({ cardText }) {
  return <div className="roll-out">{cardText}<div/>
}

So I did css:

@keyframes rollout {
  0% { transform: translateY(-100px); }
  100% { transform: none; }
}

.roll-out {
  animation: rollout 0.4s;
}

However, the animation only plays once, on the initial render. I want to play it every time <Card /> re-renders due to cardText change. How can I achieve it?

Upvotes: 39

Views: 37401

Answers (3)

ZYinMD
ZYinMD

Reputation: 5079

Add a key like this:

function Card({ cardText }) {
  return <div key={cardText} className="roll-out">{cardText}<div/>
}

In your code, when the div re-renders, react only changes its inner text. Adding a key will make react think it's a different div when the key changes, so it'll unmount it and mount again.

Upvotes: 75

ezio4df
ezio4df

Reputation: 4135

To force element to re-render you can simply change its key prop which will trigger a render making react think its another element

Refer this answer: https://stackoverflow.com/a/35004739

function Card({
  cardText
}) {
  return <div className = "roll-out" > {
    cardText
  } </div>
}

ReactDOM.render( (<Card cardText="Hey There" />) , document.getElementById('root'))
@keyframes rollout {
  0% {
    transform: translateY(-100px);
  }
  100% {
    transform: translateY(0);
  }
}

.roll-out {
  animation: .4s rollout;
}
<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>

Upvotes: 3

Kai Salmon
Kai Salmon

Reputation: 365

The trick here is to use a random key field on your card element. React's diffing algorithm considers elements with the same key as the same, so randomizing the key will make react consider each rerendered element as new, so will removed the old element from the DOM and add a brand new one

Here is a demo using @aXuser264 's code as a base.

class Card extends React.Component{
   onClick = ()=>this.forceUpdate();
   render(){
       return <div key={Math.random()} className="roll-out" onClick={this.onClick}> {
    this.props.cardText
     } </div>
  }
}

ReactDOM.render( (<Card cardText="Hey There" />) , document.getElementById('root'))
@keyframes rollout {
  0% {
    transform: translateY(-100px);
  }
  100% {
    transform: translateY(0);
  }
}

.roll-out {
  animation: .4s rollout;
}
<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>

Upvotes: 14

Related Questions