Fix concurrency bug in results view
In the results view, `setState` was used to set some state, and then `loadResults` was called to set some other state. However, `setState` is asynchronous, so the `this.state` in `loadResults` was not the state that was set before the call. This commit fixes it by combining the two `setState` calls into one. The logic was hard to follow, so I'm not sure if this is the correct fix. The `shouldKeepOldResultsWhileRendering` state seems to be unnecessary now since everything is being done in `setState` call, but I'm not sure about that.
This commit is contained in:
@@ -104,7 +104,6 @@ export class ResultsApp extends React.Component<
|
||||
queryPath: msg.queryPath,
|
||||
});
|
||||
|
||||
void this.loadResults();
|
||||
break;
|
||||
case "showInterpretedPage": {
|
||||
const tableName =
|
||||
@@ -141,7 +140,6 @@ export class ResultsApp extends React.Component<
|
||||
queryName: msg.queryName,
|
||||
queryPath: msg.queryPath,
|
||||
});
|
||||
void this.loadResults();
|
||||
break;
|
||||
}
|
||||
case "resultsUpdating":
|
||||
@@ -164,49 +162,30 @@ export class ResultsApp extends React.Component<
|
||||
|
||||
private updateStateWithNewResultsInfo(resultsInfo: ResultsInfo): void {
|
||||
this.setState((prevState) => {
|
||||
const stateWithDisplayedResults = (
|
||||
displayedResults: ResultsState,
|
||||
): ResultsViewState => ({
|
||||
displayedResults,
|
||||
isExpectingResultsUpdate: prevState.isExpectingResultsUpdate,
|
||||
nextResultsInfo: resultsInfo,
|
||||
});
|
||||
|
||||
if (!prevState.isExpectingResultsUpdate && resultsInfo === null) {
|
||||
// No results to display
|
||||
return stateWithDisplayedResults({
|
||||
resultsInfo: null,
|
||||
results: null,
|
||||
errorMessage: "No results to display",
|
||||
});
|
||||
}
|
||||
if (!resultsInfo || !resultsInfo.shouldKeepOldResultsWhileRendering) {
|
||||
if (resultsInfo === null) {
|
||||
if (prevState.isExpectingResultsUpdate) {
|
||||
// Display loading message
|
||||
return stateWithDisplayedResults({
|
||||
return {
|
||||
displayedResults: {
|
||||
resultsInfo: null,
|
||||
results: null,
|
||||
errorMessage: "Loading results…",
|
||||
});
|
||||
},
|
||||
isExpectingResultsUpdate: prevState.isExpectingResultsUpdate,
|
||||
nextResultsInfo: resultsInfo,
|
||||
};
|
||||
} else {
|
||||
// No results to display
|
||||
return {
|
||||
displayedResults: {
|
||||
resultsInfo: null,
|
||||
results: null,
|
||||
errorMessage: "No results to display",
|
||||
},
|
||||
isExpectingResultsUpdate: prevState.isExpectingResultsUpdate,
|
||||
nextResultsInfo: resultsInfo,
|
||||
};
|
||||
}
|
||||
return stateWithDisplayedResults(prevState.displayedResults);
|
||||
});
|
||||
}
|
||||
|
||||
private getResultSets(resultsInfo: ResultsInfo): readonly ResultSet[] {
|
||||
const parsedResultSets = resultsInfo.parsedResultSets;
|
||||
const resultSet = parsedResultSets.resultSet;
|
||||
if (!resultSet.t) {
|
||||
throw new Error(
|
||||
'Missing result set type. Should be either "InterpretedResultSet" or "RawResultSet".',
|
||||
);
|
||||
}
|
||||
return [resultSet];
|
||||
}
|
||||
|
||||
private async loadResults(): Promise<void> {
|
||||
const resultsInfo = this.state.nextResultsInfo;
|
||||
if (resultsInfo === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let results: Results | null = null;
|
||||
@@ -229,11 +208,6 @@ export class ResultsApp extends React.Component<
|
||||
statusText = `Error loading results: ${errorMessage}`;
|
||||
}
|
||||
|
||||
this.setState((prevState) => {
|
||||
// Only set state if this results info is still current.
|
||||
if (resultsInfo !== prevState.nextResultsInfo) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
displayedResults: {
|
||||
resultsInfo,
|
||||
@@ -246,6 +220,17 @@ export class ResultsApp extends React.Component<
|
||||
});
|
||||
}
|
||||
|
||||
private getResultSets(resultsInfo: ResultsInfo): readonly ResultSet[] {
|
||||
const parsedResultSets = resultsInfo.parsedResultSets;
|
||||
const resultSet = parsedResultSets.resultSet;
|
||||
if (!resultSet.t) {
|
||||
throw new Error(
|
||||
'Missing result set type. Should be either "InterpretedResultSet" or "RawResultSet".',
|
||||
);
|
||||
}
|
||||
return [resultSet];
|
||||
}
|
||||
|
||||
private getSortStates(
|
||||
resultsInfo: ResultsInfo,
|
||||
): Map<string, RawResultsSortState> {
|
||||
|
||||
Reference in New Issue
Block a user