Reputation: 4177
I am relatively new to ReactJS. I really like the way react renders data. However, I observe that there is some weird behaviour when I start using asynchronous calls to retrieve and render server side data. I have a component which calls a child component and renders server side data.
The server side calls are asynchronous calls. My code is something like:
class myComponent extends component {
constructor(props) {
super(props);
this.componentDidMount = this.componentDidMount.bind(this);
this.state = {myVariable: []};
}
this.componentDidMount() {
fetch() => { server side async call to retrieve data
this.setState({myVariable: serverData});
}
render() {
<div className="myClass">
<div className="renderMyBox">
<div> {this.state.myVariable} </div>
</div>
</div>
}
}
The problem I face is that. the first two div's are rendered immediately on the server and then there's almost a 1 second delay where in there's an empty div and then the state is set due to the async call which goes through. Then the change in state triggers a re-render.
Is there any way I can force the render not to happen until the async call succeeds and the state is set? Is there a workaround?
Upvotes: 1
Views: 288
Reputation: 5742
As elmaister pointed out, you can return nothing until there is data. This can be handled by observing an isReady
variable:
class myComponent extends component {
constructor(props) {
super(props);
this.componentDidMount = this.componentDidMount.bind(this);
this.state = { myVariable: [], isReady: false };
}
this.componentDidMount() {
fetch() => { server side async call to retrieve data
this.setState({
myVariable: serverData,
isReady: true
});
}
render() {
if (this.state.isReady) {
return <div className="myClass">
<div className="renderMyBox">
<div> {this.state.myVariable} </div>
</div>
</div>
}
}
}
Upvotes: 2
Reputation: 530
you can use setState in fetch, or use jquery.ajax({ async: false })
.
function getData(url) {
var response = null;
window.jQuery.ajax(
{
url: url,
dataType: 'json',
async: false,
success: function(data) {
response = data;
}.bind(this),
});
return response;
}
If you want no-render before your request, you can add this:
render() {
if(this.state.myVariable.length == 0){
return null;
}
...your code
}
An usual way is setting a loading
variable:
constructor(){
this.state = {
data: defaultData,
loading: true
};
}
componentDidMount(){
request.done(data){
this.setState({
data: data,
loading: false,
})
}
}
render() {
if(this.state.loading){
//return loading style
}
...your code
}
Upvotes: 0