How to replay a CSS3 animation in Reactjs
ReactJS uses key
attribute to distinguish between elements in the diffing algorithm. So, the first time your component loads , react assumes it as new element and renders it accordingly. But next time it tries to render the same element with different data , react feels that it has the same structure and only replaces the new data with old data.
So to apply animations for every change, we need to tell react that this is a new component. This can be done by providing a key
to the element with your animation class. And key can be randomly generated using any random number generator( I generally use shortid
).
For working example, please refer: this
How to trigger a CSS animation on EVERY TIME a react component re-renders
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.
ReactJS, CSS and SVG animations, and re-rendering
React is reusing the elements, therefore the animations won't replay b/c they've already played for the current elements.
I think it's easier to resort to dom operations in this situation, versus some setState
trickery.
https://codepen.io/guanzo/pen/vpdPzX?editors=0110
Store the refs to the 2 elements, then trigger the animations with JS.
class Component extends React.Component {
onClick() {
this.svgAnimate.beginElement()//triggers animation
this.square.style.animation = 'none';//override css animation
this.square.offsetHeight; /* trigger reflow */
this.square.style.animation = null; //fallback to css animation
}
render() {
console.log('rendering');
return (
<div onClick={() => this.onClick()}>
<svg>
<path
stroke="blue"
strokeWidth="10"
fill="transparent"
d="M50 10 a 40 40 0 0 1 0 80 a 40 40 0 0 1 0 -80"
strokeDasharray="251.2,251.2">
<animate
ref={(svgAnimate) => { this.svgAnimate = svgAnimate; }}
attributeType="css"
attributeName="stroke-dasharray"
from="0" to="251.2" dur="1s" />
</path>
</svg>
<div id="nonSvgBox"
ref={(square) => { this.square = square; }}
></div>
</div>
);
}
}
ReactDOM.render(<Component />, document.getElementById('app'));
How can I animate a react.js component onclick and detect the end of the animation
Upon clicks you can update the state, add a class and record the animationend
event.
class ClickMe extends React.Component {
constructor(props) {
super(props)
this.state = { fade: false }
}
render() {
const fade = this.state.fade
return (
<button
ref='button'
onClick={() => this.setState({ fade: true })}
onAnimationEnd={() => this.setState({ fade: false })}
className={fade ? 'fade' : ''}>
Click me!
</button>
)
}
}
See the plnkr: https://next.plnkr.co/edit/gbt0W4SQhnZILlmQ?open=Hello.js&deferRun=1&preview
Edit: Updated to reflect current React, which supports animationend events.
Restart animation in CSS3: any better way than removing the element?
Just set the animation
property via JavaScript to "none"
and then set a timeout that changes the property to ""
, so it inherits from the CSS again.
Demo for Webkit here: http://jsfiddle.net/leaverou/xK6sa/
However, keep in mind that in real world usage, you should also include -moz- (at least).
React - animate mount and unmount of a single component
This is a bit lengthy but I've used all the native events and methods to achieve this animation. No ReactCSSTransitionGroup
, ReactTransitionGroup
and etc.
Things I've used
- React lifecycle methods
onTransitionEnd
event
How this works
- Mount the element based on the mount prop passed(
mounted
) and with default style(opacity: 0
) - After mount or update, use
componentDidMount
(componentWillReceiveProps
for further updates)to change the style (opacity: 1
) with a timeout(to make it async). - During unmount, pass a prop to the component to identify unmount, change the style again(
opacity: 0
),onTransitionEnd
, remove unmount the element from the DOM.
Continue the cycle.
Go through the code, you'll understand. If any clarification is needed, please leave a comment.
class App extends React.Component{
constructor(props) {
super(props)
this.transitionEnd = this.transitionEnd.bind(this)
this.mountStyle = this.mountStyle.bind(this)
this.unMountStyle = this.unMountStyle.bind(this)
this.state ={ //base css
show: true,
style :{
fontSize: 60,
opacity: 0,
transition: 'all 2s ease',
}
}
}
componentWillReceiveProps(newProps) { // check for the mounted props
if(!newProps.mounted)
return this.unMountStyle() // call outro animation when mounted prop is false
this.setState({ // remount the node when the mounted prop is true
show: true
})
setTimeout(this.mountStyle, 10) // call the into animation
}
unMountStyle() { // css for unmount animation
this.setState({
style: {
fontSize: 60,
opacity: 0,
transition: 'all 1s ease',
}
})
}
mountStyle() { // css for mount animation
this.setState({
style: {
fontSize: 60,
opacity: 1,
transition: 'all 1s ease',
}
})
}
componentDidMount(){
setTimeout(this.mountStyle, 10) // call the into animation
}
transitionEnd(){
if(!this.props.mounted){ // remove the node on transition end when the mounted prop is false
this.setState({
show: false
})
}
}
render() {
return this.state.show && <h1 style={this.state.style} onTransitionEnd={this.transitionEnd}>Hello</h1>
}
}
class Parent extends React.Component{
constructor(props){
super(props)
this.buttonClick = this.buttonClick.bind(this)
this.state = {
showChild: true,
}
}
buttonClick(){
this.setState({
showChild: !this.state.showChild
})
}
render(){
return <div>
<App onTransitionEnd={this.transitionEnd} mounted={this.state.showChild}/>
<button onClick={this.buttonClick}>{this.state.showChild ? 'Unmount': 'Mount'}</button>
</div>
}
}
ReactDOM.render(<Parent />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
React css webkit animation is not working after setState
I suggest it's a problem with your css rather than React
. What you missed is a value for animation-iteration-count
.
You can make it works by adding infinite
to your -webkit-animation
rule.
-webkit-animation:enemy 1s linear forwards infinite;
More information about animation
can be found here: https://www.w3schools.com/cssref/css3_pr_animation.asp
React apply css classes dynamically
Well, here's an example. In short, I'd use css transitions, not keyframes for something as simple as this.
class App extends React.Component { constructor(props) { super(props) this.state = {show: false} this.show = this.show.bind(this) } show() { this.setState(prevState => ({show: !prevState.show})) } render() { return ( <div className={'wrapper' + (this.state.show ? ' show' : '')}> <div> <button onClick={this.show}>{this.state.show ? 'hide' : 'show'}</button> </div> <div className="one">one</div> <div className="two">two</div> </div> ) }}
ReactDOM.render( <App />, document.getElementById('root'));
body { margin: 0;}
.wrapper { overflow: hidden; white-space: nowrap;}
.one, .two { background: #333; border: 2px solid #787567; box-sizing: border-box; color: #fff; display: inline-block; font-family: arial; overflow: hidden; padding: 20px; text-align: center; transition: border 0.2s, padding 0.2s, width 0.2s;}
.one { width: 100%;}.two { border-width: 2px 0; padding: 20px 0; width: 0;}
.show .one, .show .two { border-width: 2px; padding: 20px; width: 50%;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><div id="root"></div>
Related Topics
Detect Browser Graphics Performance
Find Unused CSS Rule and Js Script in a Web Project
How to Prevent Material Icon Text from Showing Up When Google's Js Fails to Convert Them
Why Do Developers Append a Query String in JavaScript Files' Stylesheet Links
Using Cookies to Retain Stylesheet Preference Across Website
Onclick JavaScript Function Working Only on Second Click
How to Parse CSS Font Shorthand Format
Inset-Shadow on HTML5 Canvas Image
iOS 11 Getusermedia Not Working
How to Check If Character Isn't Supported by the User's Browser in JavaScript
Uncaught Domexception: Failed to Read the 'Rules' Property from 'Cssstylesheet'
Disable Inertia Scroll for "Single-Page" Webapp
Jquery Calendar Time Selection Suggestion
Onclick Show Div, But Hide When Other One Is Clicked
Jquery .Css() Function with Variables and Multiple Values
Using Modernizr and Jquery to Animate If CSS3 Transitions Don't Exist