Example: http://www.webpackbin.com/N16jKp-cz
import React, {PureComponent } from 'react';
import {render} from 'react-dom';
import {Motion, spring} from 'react-motion';
class App extends PureComponent {
constructor(...args) {
super(...args);
this.state = {
x: spring(10)
}
this.onRest = this.onRest.bind(this);
}
onRest() {
// changing to a number value
this.setState({
x: 100
});
}
render() {
return (
<Motion defaultStyle={{x: 0}} style={this.state} onRest={this.onRest}>
{interpolatingStyle => {
return (
<div>
{/* on final render this should be '100' but it is the last spring value: '10' */}
interpolated x: {interpolatingStyle.x} <br/>
{/* on final render this renders '100' as expected */}
current x: {JSON.stringify(this.state.x)}
</div>
)
}}
</Motion>
)
}
}
render(<App />, document.getElementById('app'));
Workaround: put update on the end of the stack
onRest() {
setTimeout(() => {
this.setState({
x: 100
});
});
};
I am not sure if it is related, but I am also finding that the interpolatingStyle can pass the previous interpolatingStyle value when style is changed to a fixed value mid transition
I have ended up doing something like this to get around all issues:
render() {
const final = this.getFinal();
const isNotMoving = start.x == 0 && start.y == 0 && final.x == 0 && final.y == 0;
return (
<Motion defaultStyle={start} style={final} onRest={this.onRest}>
{(current) => {
// while `start` might equal {x: 0, y: 0} and `final` might equal {x: 0, y: 0}, current can be the last computed value
return (
<div style={isNotMoving ? {} : getMovement(current)} >
{this.props.children}
</div>
);
}}
</Motion>
);
}
Not sure how to proceed on this one :)
Yeah setTimeout is necessary to use with onRest. I reckon this has something to do with async nature/batching of setState in React.
We can probably switch to setState(pureCallback) notation as now recommended. Hopefully it would eliminate the problem.
You may check https://github.com/nkbt/react-motion-loop with my workaround, which is the same...
if you check source of react-collapse@3 you will find fairly ugly but working solution with instance vars. I had to figure out when animation ends properly and comparing with end values is not the right one, since spring can go into negative values in many cases.
Most helpful comment
Yeah setTimeout is necessary to use with onRest. I reckon this has something to do with async nature/batching of setState in React.
We can probably switch to setState(pureCallback) notation as now recommended. Hopefully it would eliminate the problem.
You may check https://github.com/nkbt/react-motion-loop with my workaround, which is the same...