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