From f428db282c277e70ccf192c3593feba1f98d3695 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 8 Jan 2019 13:32:08 +0100 Subject: [PATCH] fix: Remove the onRenderError prop and add an ErrorBoundary component --- packages/grafana-ui/src/types/panel.ts | 1 - .../src/visualizations/Graph/Graph.tsx | 5 +- .../ErrorBoundary/ErrorBoundary.tsx | 47 +++++++++++++++++++ .../features/dashboard/dashgrid/DataPanel.tsx | 29 ++++++++---- .../dashboard/dashgrid/PanelChrome.tsx | 3 +- .../app/plugins/panel/graph2/GraphPanel.tsx | 5 +- 6 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 public/app/core/components/ErrorBoundary/ErrorBoundary.tsx diff --git a/packages/grafana-ui/src/types/panel.ts b/packages/grafana-ui/src/types/panel.ts index cf808f514de..44336555a81 100644 --- a/packages/grafana-ui/src/types/panel.ts +++ b/packages/grafana-ui/src/types/panel.ts @@ -9,7 +9,6 @@ export interface PanelProps { renderCounter: number; width: number; height: number; - onRenderError: () => void; } export interface PanelOptionsProps { diff --git a/packages/grafana-ui/src/visualizations/Graph/Graph.tsx b/packages/grafana-ui/src/visualizations/Graph/Graph.tsx index b3f2120639c..ad038cebcda 100644 --- a/packages/grafana-ui/src/visualizations/Graph/Graph.tsx +++ b/packages/grafana-ui/src/visualizations/Graph/Graph.tsx @@ -13,7 +13,6 @@ interface GraphProps { showBars?: boolean; width: number; height: number; - onRenderError: () => void; } export class Graph extends PureComponent { @@ -38,7 +37,7 @@ export class Graph extends PureComponent { return; } - const { width, timeSeries, timeRange, showLines, showBars, showPoints, onRenderError } = this.props; + const { width, timeSeries, timeRange, showLines, showBars, showPoints } = this.props; if (!width) { return; @@ -99,7 +98,7 @@ export class Graph extends PureComponent { $.plot(this.element, timeSeries, flotOptions); } catch (err) { console.log('Graph rendering error', err, flotOptions, timeSeries); - onRenderError(); + throw new Error('Error rendering panel'); } } diff --git a/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx b/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx new file mode 100644 index 00000000000..ed068819adc --- /dev/null +++ b/public/app/core/components/ErrorBoundary/ErrorBoundary.tsx @@ -0,0 +1,47 @@ +import React, { Component } from 'react'; + +interface ErrorInfo { + componentStack: string; +} + +interface RenderProps { + error: Error; + errorInfo: ErrorInfo; +} + +interface Props { + children: (r: RenderProps) => JSX.Element; +} + +interface State { + error: Error; + errorInfo: ErrorInfo; +} + +class ErrorBoundary extends Component { + constructor(props) { + super(props); + this.state = { error: null, errorInfo: null }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo) { + this.setState({ + error: error, + errorInfo: errorInfo + }); + } + + render() { + const { error, errorInfo } = this.state; + return ( + <> + {this.props.children({ + error, + errorInfo, + })} + + ); + } +} + +export default ErrorBoundary; diff --git a/public/app/features/dashboard/dashgrid/DataPanel.tsx b/public/app/features/dashboard/dashgrid/DataPanel.tsx index 4cd9460802a..fa21276d7a2 100644 --- a/public/app/features/dashboard/dashgrid/DataPanel.tsx +++ b/public/app/features/dashboard/dashgrid/DataPanel.tsx @@ -1,6 +1,7 @@ // Library import React, { Component } from 'react'; import Tooltip from 'app/core/components/Tooltip/Tooltip'; +import ErrorBoundary from 'app/core/components/ErrorBoundary/ErrorBoundary'; // Services import { getDatasourceSrv, DatasourceSrv } from 'app/features/plugins/datasource_srv'; @@ -13,10 +14,11 @@ import { DataQueryOptions, DataQueryResponse } from 'app/types'; import { TimeRange, TimeSeries, LoadingState } from '@grafana/ui'; import { Themes } from 'app/core/components/Tooltip/Popper'; +const DEFAULT_PLUGIN_ERROR = 'Error in plugin'; + interface RenderProps { loading: LoadingState; timeSeries: TimeSeries[]; - onRenderError: () => void; } export interface Props { @@ -147,10 +149,6 @@ export class DataPanel extends Component { } } - onRenderError = () => { - this.onError('Error rendering panel'); - } - render() { const { queries } = this.props; const { response, loading, isFirstLoad } = this.state; @@ -172,11 +170,22 @@ export class DataPanel extends Component { return ( <> {this.renderLoadingStates()} - {this.props.children({ - timeSeries, - loading, - onRenderError: this.onRenderError - })} + + {({error, errorInfo}) => { + if (errorInfo) { + this.onError(error.message || DEFAULT_PLUGIN_ERROR); + return null; + } + return ( + <> + {this.props.children({ + timeSeries, + loading, + })} + + ); + }} + ); } diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 90d66a14cd3..84e11511453 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -114,7 +114,7 @@ export class PanelChrome extends PureComponent { widthPixels={width} refreshCounter={refreshCounter} > - {({ loading, timeSeries, onRenderError }) => { + {({ loading, timeSeries }) => { return (
{ width={width} height={height - PANEL_HEADER_HEIGHT} renderCounter={renderCounter} - onRenderError={onRenderError} />
); diff --git a/public/app/plugins/panel/graph2/GraphPanel.tsx b/public/app/plugins/panel/graph2/GraphPanel.tsx index 49d2ac3e4e4..2c21c7f0e15 100644 --- a/public/app/plugins/panel/graph2/GraphPanel.tsx +++ b/public/app/plugins/panel/graph2/GraphPanel.tsx @@ -10,12 +10,12 @@ import { Options } from './types'; interface Props extends PanelProps {} export class GraphPanel extends PureComponent { - constructor(props) { + constructor(props: Props) { super(props); } render() { - const { timeSeries, timeRange, width, height, onRenderError } = this.props; + const { timeSeries, timeRange, width, height } = this.props; const { showLines, showBars, showPoints } = this.props.options; const vmSeries = processTimeSeries({ @@ -33,7 +33,6 @@ export class GraphPanel extends PureComponent { showBars={showBars} width={width} height={height} - onRenderError={onRenderError} /> ); }