Merge pull request #15113 from grafana/fix/explore-set-state-on-unmounted
Fix setState on unmounted component in Loki and Prometheus QueryField
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
// https://github.com/facebook/react/issues/5465
|
||||
|
||||
export interface CancelablePromise<T> {
|
||||
promise: Promise<T>;
|
||||
cancel: () => void;
|
||||
}
|
||||
|
||||
export const makePromiseCancelable = <T>(promise: Promise<T>): CancelablePromise<T> => {
|
||||
let hasCanceled_ = false;
|
||||
|
||||
const wrappedPromise = new Promise<T>((resolve, reject) => {
|
||||
promise.then(val => (hasCanceled_ ? reject({ isCanceled: true }) : resolve(val)));
|
||||
promise.catch(error => (hasCanceled_ ? reject({ isCanceled: true }) : reject(error)));
|
||||
});
|
||||
|
||||
return {
|
||||
promise: wrappedPromise,
|
||||
cancel() {
|
||||
hasCanceled_ = true;
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -16,6 +16,7 @@ import RunnerPlugin from 'app/features/explore/slate-plugins/runner';
|
||||
// Types
|
||||
import { LokiQuery } from '../types';
|
||||
import { TypeaheadOutput } from 'app/types/explore';
|
||||
import { makePromiseCancelable, CancelablePromise } from 'app/core/utils/CancelablePromise';
|
||||
|
||||
const PRISM_SYNTAX = 'promql';
|
||||
|
||||
@@ -85,6 +86,7 @@ class LokiQueryField extends React.PureComponent<LokiQueryFieldProps, LokiQueryF
|
||||
languageProvider: any;
|
||||
modifiedSearch: string;
|
||||
modifiedQuery: string;
|
||||
languageProviderInitializationPromise: CancelablePromise<any>;
|
||||
|
||||
constructor(props: LokiQueryFieldProps, context) {
|
||||
super(props, context);
|
||||
@@ -112,12 +114,24 @@ class LokiQueryField extends React.PureComponent<LokiQueryFieldProps, LokiQueryF
|
||||
|
||||
componentDidMount() {
|
||||
if (this.languageProvider) {
|
||||
this.languageProvider
|
||||
.start()
|
||||
this.languageProviderInitializationPromise = makePromiseCancelable(this.languageProvider.start());
|
||||
|
||||
this.languageProviderInitializationPromise.promise
|
||||
.then(remaining => {
|
||||
remaining.map(task => task.then(this.onUpdateLanguage).catch(() => {}));
|
||||
})
|
||||
.then(() => this.onUpdateLanguage());
|
||||
.then(() => this.onUpdateLanguage())
|
||||
.catch(({ isCanceled }) => {
|
||||
if (isCanceled) {
|
||||
console.warn('LokiQueryField has unmounted, language provider intialization was canceled');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.languageProviderInitializationPromise) {
|
||||
this.languageProviderInitializationPromise.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import BracesPlugin from 'app/features/explore/slate-plugins/braces';
|
||||
import RunnerPlugin from 'app/features/explore/slate-plugins/runner';
|
||||
import QueryField, { TypeaheadInput, QueryFieldState } from 'app/features/explore/QueryField';
|
||||
import { PromQuery } from '../types';
|
||||
import { CancelablePromise, makePromiseCancelable } from 'app/core/utils/CancelablePromise';
|
||||
|
||||
const HISTOGRAM_GROUP = '__histograms__';
|
||||
const METRIC_MARK = 'metric';
|
||||
@@ -104,6 +105,7 @@ interface PromQueryFieldState {
|
||||
class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryFieldState> {
|
||||
plugins: any[];
|
||||
languageProvider: any;
|
||||
languageProviderInitializationPromise: CancelablePromise<any>;
|
||||
|
||||
constructor(props: PromQueryFieldProps, context) {
|
||||
super(props, context);
|
||||
@@ -129,12 +131,23 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
|
||||
|
||||
componentDidMount() {
|
||||
if (this.languageProvider) {
|
||||
this.languageProvider
|
||||
.start()
|
||||
this.languageProviderInitializationPromise = makePromiseCancelable(this.languageProvider.start());
|
||||
this.languageProviderInitializationPromise.promise
|
||||
.then(remaining => {
|
||||
remaining.map(task => task.then(this.onUpdateLanguage).catch(() => {}));
|
||||
})
|
||||
.then(() => this.onUpdateLanguage());
|
||||
.then(() => this.onUpdateLanguage())
|
||||
.catch(({ isCanceled }) => {
|
||||
if (isCanceled) {
|
||||
console.warn('PromQueryField has unmounted, language provider intialization was canceled');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.languageProviderInitializationPromise) {
|
||||
this.languageProviderInitializationPromise.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user