This onRest callback doesn't work:
@autobind
handleRest() {
this.setState(getNextTransitionState);
}
However, this one works as expected:
@autobind
handleRest() {
window.setTimeout(() => {
this.setState(getNextTransitionState);
}, 0);
}
Actually the second example doesn't quite work, since the transition loses its momentum :(
Ehhh, @appsforartists
Yeah. I've noticed this too, but haven't looked too closely into a fix yet.
@chenglou, you think adding a call to startAnimationIfNecessary immediately after onRest would fix it? Looks like the whole body is wrapped in defaultRaf, so that should put you on the next frame and kick off an animation if something changed (presuming startAnimationIfNecessary does what it says on the tin 😉).
I forgot to ask this last night, but @arcanis, can you talk more about what you expected when you said "loses its momentum"? onRest should only be called when the system is at rest - that is, there is no more energy left. If there is still momentum, onRest will not yet trigger.
If you want it to be perpetually moving, perhaps you should measure if the interpolated value is within some threshold of the destination, and when it is, call setState to change the destination.
@appsforartists Yep, I tried to check thresholds to trigger followup animations while there was still some momentum, but unfortunately it wasn't precise enough: some animations were too fast relative to others, it caused issues with bouncing (since the threshold could be triggered multiple times), curves were messed, etc. In the end, we went with Animated, which gave us a better control over sequenced animations.
Having similar problem. Calling setState in onRest that affects styles does not work.
This is simple component which fades out old text and fade is new one.
But to make it work I have to wrap setState in onRest callback with setTimeout, otherwise new step value is ignored in Motion. So basically it prevents setting new target value in onRest callback. Would be great if thats fixable, don't like these setTimeout workarounds.
const AnimationSwitch = React.createClass({
getInitialState: function () {
return {
step: 1
};
},
componentWillReceiveProps: function(nextProps) {
if (this.props.text !== nextProps.text) {
this.setState({
text: this.props.text,
step: 0
});
}
},
handleAnimationEnd: function () {
if (this.state.step == 0) {
this.setState({
step: 1
});
}
}
},
render: function () {
const { step } = this.state;
const text = step === 0 ? this.state.text : this.props.text;
return (
<Motion
style={
{opacity: spring(step)}
}
onRest={this.handleAnimationEnd}
>
{interpolatingStyle => <span style={interpolatingStyle}>{text}</span>}
</Motion>
);
}
});
Yeah. See https://github.com/nkbt/react-motion-loop for example
On Fri, 3 Jun 2016 at 21:03, Jarda Kotěšovec [email protected]
wrote:
Having similar problem. Calling setState in onRest that affects styles
does not work.
This is simple component which fades out old text and fade is new one.But to make it work I have to wrap setState in onRest callback to
setTimeout, otherwise new step value is ignored in Motion. So basically
it prevents setting new target value in onRest callback. Would be great
if thats fixable, don't like these setTimeout workarounds.const AnimationSwitch = React.createClass({
getInitialState: function () {
return {
step: 1
};
},
componentWillReceiveProps: function(nextProps) {
if (this.props.text !== nextProps.text) {
this.setState({
text: this.props.text,
step: 0
});
}
},
handleAnimationEnd: function () {
if (this.state.step == 0) {
this.setState({
step: 1
});
}
}
},
render: function () {
const { step } = this.state;
const text = step === 0 ? this.state.text : this.props.text;
return (
style={
{opacity: spring(step)}
}
onRest={this.handleAnimationEnd}
>
{interpolatingStyle => }
);
}
});—
You are receiving this because you are subscribed to this thread.Reply to this email directly, view it on GitHub
https://github.com/chenglou/react-motion/issues/322#issuecomment-223551489,
or mute the thread
https://github.com/notifications/unsubscribe/AAKsoBH2V_Wi9yyQQ0sGYTWH5CLNCl7Cks5qIAoJgaJpZM4IPKNw
.
@nkbt yep.. delaying setState works... But if its possible to make it work without it I think it would be helpful, because you get kind of undefined behavior otherwise.. and it takes time to find out why..
I reckon you can try to do forceUpdate() after that. Should work too, but I haven't checked.
Actually right, deferring state change onRest makes animations lose momentum and causes delays. It is not quite awesome in some edge cases.
Here in example I need to go from RESIZE to REST and then to STABLE state. If I do not delay REST, next animation is blocked and container is not resized. If I do, then container is resized with a slight delay, which looks a bit odd

https://github.com/chenglou/react-motion/issues/343
https://github.com/chenglou/react-motion/issues/390
I think this bug is very common. Looking forward to fix it.
This seems like a major bug and counter to the way you expect react to work by setting state leading to rerender. Is there plans to fix this?
@nkbt
@appsforartists
Update about this issue.
I tried to investigate this as I encountered it in my project https://github.com/NdYAG/react-onepage/blob/master/src/slider.js#L13
As @appsforartists said adding a call of startAnimationIfNecessary after onRest could help avoid the setTimeout/requestAnimationFrame workaround. However it work as setTimeout, which triggers the same problem @nkbt demonstrated in his GIF.
What I found is that, setting props in onRest, which triggers componentWillReceiveProps in Motion.js, won't push this new unreadPropStyle into state.currentStyle when animationID is not null.
Most helpful comment
This seems like a major bug and counter to the way you expect react to work by setting state leading to rerender. Is there plans to fix this?