I don't have a reproducible example for this but basically what I'm doing is this:
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
let that = this;
fetch(...).then((response) => {
response.json().then((data) => that.setState(data);)
window.setTimeout(that.tick.bind(that), 1000);
});
}
tick() {
/* do some calculation to update the state */
let state = {...};
this.setState(state);
console.log("Set state: ", state);
if (someCondition)
window.setTimeout(this.tick.bind(this), 1000);
}
render() {
console.log("Render state: ", this.state);
return ( ... react output ... );
}
}
I fetch some data, add it to the state, then start a timer that calls tick() once per second. tick() updates the state, logs the new state (note - the value I'm setting not the value of this.state) and then decides whether to set a new timer. render() logs what its idea of the state is and then returns the rendered content.
This all works. I can see in the console the state value I'm setting and then render()'s idea of the state being the same as that value I've just set.
The problem comes when I run it all through webpack to create a single JS bundle. Then setState() stops doing what I expect. I can still see the value that I'm feeding to setState() but the state value seen by render() is {} until I stop setting new timers. Then the state value seen by render() updates and the content renders correctly.
The output of webpack is pretty impenetrable so I'm having a bit of trouble tracking down what has changed to cause this difference in behaviour. Is this a well-known gotcha?
I'm aware that setState() is not guaranteed to be synchronous and that I shouldn't expect the value of this.state to update immediately - but I did expect it would at least have updated by the time render() is next called.
from React client-side rendered components - state doesn't update while script is still running
No comments:
Post a Comment