I have a situation where React renders before data fetched from Oracle database using Meteor.call
is ready, and I can’t figure out how to solve it.
The below handleOnDrop
method handles dropped files and works for files that don’t require a Meteor.call
as determined in parserHelper
:
/**
* Event handler for files dropped on Dropzone.
* @param {Array} files List of File objects from a dropzone.
*/
handleOnDrop(files) {
if (files.length === 0) {
return;
}
const droppedFile = files[0];
const reader = new FileReader();
reader.onload = (event) => {
const parserHelper = new ParserHelper(this.state.plateData, event, droppedFile);
this.setState({
droppedFile: droppedFile.name,
plateBarcode: parserHelper.plateBarcode,
plateData: parserHelper.plateData,
fileType: parserHelper.fileType,
types: parserHelper.types,
compounds: parserHelper.compounds,
statusData: parserHelper.statusData,
selectedStatus: parserHelper.selectedStatus,
tableData: parserHelper.tableData,
columns: parserHelper.columns,
parsed: parserHelper.parsed,
});
};
reader.readAsText(droppedFile);
}
The parserHelper
constructor calls this method for certain dropped files where we need data from Oracle (the database returns data nicely):
parseEnvision() {
const parser = new ParseEnvision(this._event.target.result);
const newPlate = parser.plate;
const plateBarcode = parser.plateBarcode;
Meteor.call('getPlate', plateBarcode, function(error, plateRecord) {
if (error) {
throw new Error(`getPlate failed for barcode: ${plateBarcode}`);
}
const plate = new Plate({
rowSize: plateRecord._rowSize,
columnSize: plateRecord._columnSize,
wells: plateRecord._wells,
});
newPlate.merge(plate);
const plateData = this._plateData
? this._plateData.merge(newPlate)
: newPlate;
const helper = new PlateHelper(plateData);
this._plateBarcode = plateBarcode;
this._plateData = plateData;
this._types = plateData.types;
this._compounds = helper.getUniqueCompounds();
this._statusData = prepareStatusData(plateData.types);
this._parsed = true;
}.bind(this));
}
The render methods starts with:
render() {
if (this.state.droppedFile && !this.state.parsed) {
return <div>Loading ...</div>;
}
return (
...
And never gets beyond Loading ...
because this.state.parsed
is false
. But only so for dropped files that invokes the Meteor.call
- it renders nicely in other cases.