Reputation: 362
My goal is to make a series of requests, and upon the completion of each request, update text that indicates what step is currently being processed. Like so:
Before I get into specifics I'd like to address that as far as I know there are two ways to trigger a re-render
setState
forceUpdate
(not recommended)Neither of these methods are working in my case which is why I'm creating this question.
I read, as far as I understand, that updating state in async requests has issues with triggering re-renders. So I tried to process each async request synchronously with the recursive method processRequests
at the bottom here:
process = () => {
this.setState( { processing: true } );
const dir = RNFetchBlob.fs.dirs.MainBundleDir;
const { item } = this.state;
const requests = [
{
url: `${this.base_url}/${item.id}`,
message: 'Loading model...',
callback: function( res ) {
return new Promise( resolve => {
const model_url = JSON.parse( res.data );
RNFetchBlob.config( {
path : `${dir}/model.obj`
} ).fetch( 'GET', model_url ).then( () => resolve() )
} );
}
},
{
url: `${this.base_url}/${item.id}`,
message: 'Loading texture...',
callback: function( res ) {
return new Promise( resolve => {
const texture_url = JSON.parse( res.data );
const split = texture_url.split( '.' );
const extension = split[ split.length -1 ];
RNFetchBlob.config( {
path : `${dir}/texture.${extension}`
} ).fetch( 'GET', texture_url ).then( () => resolve() )
} );
}
}
];
this.processRequests( requests );
};
requestFileAndDownload = ( url, callback ) => {
return new Promise( resolve => {
RNFetchBlob.fetch( 'GET', url ).then( res => {
callback( res ).then( () => {
resolve();
} )
} );
} );
};
processRequests = requests => {
const request = requests.shift();
const { url, message, callback } = request;
console.log( 'message = ', message );
this.setState( { processing_text: message } );
this.requestFileAndDownload( url, callback ).then( () => {
if( requests.length ) {
this.processRequests( requests );
}
} );
};
The files are successfully downloaded but I cannot get the component to re-render in between requests. Even though the text in the state has definitely been updated, as indicated by console messages I've output:
I tried inserting forceUpdate
in a bunch of different places, but I find in general that if I ever get to the point where I feel the need to try and use forceUpdate
it never works.
Upvotes: 0
Views: 758
Reputation: 66
You should try to use the setState callback handler function in the processRequests call.
It will wait until setState finishes and the component re-renders before calling the next file download function.
this.setState( { processing_text: message }, () => {
this.requestFileAndDownload( url, callback ).then( () => {
if( requests.length ) {
this.processRequests( requests );
}
});
});
Upvotes: 3