src/common/errorWrap.tsx (68 lines of code) (raw):
import * as React from 'react';
import { BaseChartConfig, Chart } from './types';
import { BaseClass, ChartProps } from './Base';
// import { FullCrossName } from '../constants';
// import Wplaceholder from '../Wplaceholder';
import { getText } from '../ChartProvider';
interface ErrorProps {
forwardedRef?: React.Ref<any>;
}
interface ErrorState {
errorStack?: string | null;
}
/**
* errorWrap 错误捕获HOC
*
* */
/*#__PURE__*/ function errorWrap<
T extends BaseClass<ChartConfig, Props>,
ChartConfig extends BaseChartConfig,
Props extends ChartProps<ChartConfig> = ChartProps<ChartConfig>,
>(Component: T): T {
class ErrorBoundary extends React.Component<Props & ErrorProps, ErrorState> {
static isG2Chart = true;
static displayName = Component.displayName;
// static propTypes = Component.propTypes;
static defaultProps = Component.defaultProps;
static RawChart = Component;
state: ErrorState = { errorStack: null };
public chart: Chart;
public chartDom: HTMLDivElement;
public chartId: string;
public size: number[];
shouldComponentUpdate() {
if (this.state.errorStack) {
// 在update前重置error标记
// 为顾及React16.3之前的用户,因此没有将该逻辑放在getDerivedStateFromProps里
this.setState({ errorStack: null });
}
return true;
}
componentDidCatch(error: Error /*, info*/) {
// Display fallback UI
this.setState({ errorStack: error.stack });
}
// 低版本React中,复制可能用到的属性。
oldReactRef: React.RefCallback<any> = (chartInstance) => {
if (chartInstance) {
// 复制旧版本可能用到的属性
this.chart = chartInstance.chart;
this.chartId = chartInstance.chartId;
this.chartDom = chartInstance.chartDom;
this.size = chartInstance.size;
}
};
render() {
if (this.state.errorStack) {
// const { className = '', style, height } = this.props;
// @ts-ignore
const { language, locale } = Component.contextType._currentValue;
// You can render any custom fallback UI
// return <pre className={`${FullCrossName} widgets-error-info ${className}`} style={style}>{this.state.errorStack}</pre>;
// return (
// <Wplaceholder
// error
// // locale={{
// // // todo: 国际化
// // error: '图表异常',
// // }}
// style={{
// height: height ? Number(height) : undefined,
// }}
// />
// );
// @ts-ignore
return (
<Component
{...this.props}
errorInfo={getText('error', this.props?.language || language, locale)}
/>
);
}
const { forwardedRef = this.oldReactRef, ...rest } = this.props;
// @ts-ignore 将自定义的 prop 属性 “forwardedRef” 定义为 ref
return <Component ref={forwardedRef} {...(rest as Props)} />;
}
}
if (React.forwardRef) {
const forwardRefFunc = function (props: any, ref: React.Ref<any>) {
return <ErrorBoundary {...props} forwardedRef={ref} />;
};
const result = React.forwardRef(forwardRefFunc);
// @ts-ignore
result.isG2Chart = true;
// @ts-ignore
result.RawChart = Component;
result.displayName = Component.displayName;
// result.propTypes = Component.propTypes;
result.defaultProps = Component.defaultProps;
return result as unknown as T;
}
return ErrorBoundary as unknown as T;
}
export default errorWrap;