Reputation: 255
I am trying to have a "Loading" message appear before a time consuming operation takes place in React. I tried this:
var LoadingExample1 = React.createClass({
getInitialState: function () {
return {message: ""};
},
render: function () {
return (
<div>
<div>{this.state.message}</div>
<button onClick={this.doWork}>Solve</button>
</div>
)
},
doWork: function () {
this.setState({message: "Loading..."});
for (var i = 0; i < 1000000000; i++) {
;
}
this.setState({message: "Done."});
}
});
React.renderComponent(
<LoadingExample1 />,
document.getElementById("example1")
);
But it seems that the UI is updated only after the operation has been completed, which is too late. I also tried using the setState callback, but the result is the same:
var LoadingExample2 = React.createClass({
getInitialState: function () {
return {message: ""};
},
render: function () {
return (
<div>
<div>{this.state.message}</div>
<button onClick={this.doWork}>Solve</button>
</div>
)
},
doWork: function () {
this.setState({message: "Loading..."}, function () {
for (var i = 0; i < 1000000000; i++) {
;
}
this.setState({message: "Done."});
});
}
});
React.renderComponent(
<LoadingExample2 />,
document.getElementById("example2")
);
Any suggestions on what to try next?
Upvotes: 4
Views: 2443
Reputation: 1437
This is what I would do. I'd be interested in hearing if there is a better approach.
var LoadingExample3 = React.createClass({
getInitialState: function () {
return {message: ""};
},
render: function () {
return (
<div>
<div>{this.state.message}</div>
<button onClick={this.doWork}>Solve</button>
</div>
)
},
doWork: function () {
this.setState({message: "Loading..."});
this.doWorkAsync();
},
doWorkAsync: function () {
var self = this;
setTimeout(function() {
for (var i = 0; i < 1000000000; i++) {
;
}
self.setState({message: "Done."});
}, 0); // timeout of 0 ms means "run at the end of the current event loop"
}
});
React.renderComponent(
<LoadingExample3 />,
document.getElementById("example1")
);
Upvotes: 3