mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
⚠️ Add Alert.ErrorBoundary (#19923)
⚡ support ErrorBoundary message and description
This commit is contained in:
parent
7b4123258b
commit
05c2f92b69
41
components/alert/ErrorBoundary.tsx
Normal file
41
components/alert/ErrorBoundary.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import * as React from 'react';
|
||||
import Alert from '.';
|
||||
|
||||
interface ErrorBoundaryProps {
|
||||
message?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default class ErrorBoundary extends React.Component<
|
||||
ErrorBoundaryProps,
|
||||
{
|
||||
error?: Error | null;
|
||||
info: {
|
||||
componentStack?: string;
|
||||
};
|
||||
}
|
||||
> {
|
||||
state = {
|
||||
error: undefined,
|
||||
info: {
|
||||
componentStack: '',
|
||||
},
|
||||
};
|
||||
|
||||
componentDidCatch(error: Error | null, info: object) {
|
||||
this.setState({ error, info });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { message, description, children } = this.props;
|
||||
const { error, info } = this.state;
|
||||
const componentStack = info && info.componentStack ? info.componentStack : null;
|
||||
const errorMessage = typeof message === 'undefined' ? (error || '').toString() : message;
|
||||
const errorDescription = typeof description === 'undefined' ? componentStack : description;
|
||||
if (error) {
|
||||
// You can render any custom fallback UI
|
||||
return <Alert type="error" message={errorMessage} description={errorDescription} />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
@ -1,5 +1,16 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders ./components/alert/demo/error-boundary.md correctly 1`] = `
|
||||
<button
|
||||
class="ant-btn ant-btn-danger"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
Click me to throw a error
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/alert/demo/banner.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
22
components/alert/__tests__/__snapshots__/index.test.js.snap
Normal file
22
components/alert/__tests__/__snapshots__/index.test.js.snap
Normal file
@ -0,0 +1,22 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Alert ErrorBoundary 1`] = `
|
||||
<div
|
||||
class="ant-alert ant-alert-error ant-alert-with-description ant-alert-no-icon"
|
||||
data-show="true"
|
||||
>
|
||||
<span
|
||||
class="ant-alert-message"
|
||||
>
|
||||
ReferenceError: NotExisted is not defined
|
||||
</span>
|
||||
<span
|
||||
class="ant-alert-description"
|
||||
>
|
||||
|
||||
in ThrowError
|
||||
in ErrorBoundary (created by WrapperComponent)
|
||||
in WrapperComponent
|
||||
</span>
|
||||
</div>
|
||||
`;
|
@ -2,6 +2,8 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Alert from '..';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
|
||||
describe('Alert', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
@ -49,4 +51,16 @@ describe('Alert', () => {
|
||||
expect(input.getAttribute('role')).toBe('status');
|
||||
});
|
||||
});
|
||||
|
||||
const testIt = process.env.REACT === '15' ? it.skip : it;
|
||||
testIt('ErrorBoundary', () => {
|
||||
const ThrowError = () => <NotExisted />; // eslint-disable-line
|
||||
const wrapper = mount(
|
||||
<ErrorBoundary>
|
||||
<ThrowError />
|
||||
</ErrorBoundary>,
|
||||
);
|
||||
// eslint-disable-next-line jest/no-standalone-expect
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
51
components/alert/demo/error-boundary.md
Normal file
51
components/alert/demo/error-boundary.md
Normal file
@ -0,0 +1,51 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: ErrorBoundary
|
||||
en-US: React 错误处理
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
友好的 [React 错误处理](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html) 包裹组件。
|
||||
|
||||
## en-US
|
||||
|
||||
ErrorBoundary Component for making error handling easier in [React](https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html).
|
||||
|
||||
```jsx
|
||||
import { Button, Alert } from 'antd';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
|
||||
class ThrowError extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
};
|
||||
|
||||
onClick = () => {
|
||||
this.setState({
|
||||
error: new Error('An Uncaught Error'),
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { error } = this.state;
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
return (
|
||||
<Button type="danger" onClick={this.onClick}>
|
||||
Click me to throw a error
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<ErrorBoundary>
|
||||
<ThrowError />
|
||||
</ErrorBoundary>,
|
||||
mountNode,
|
||||
);
|
||||
```
|
@ -25,3 +25,10 @@ Alert component for feedback.
|
||||
| showIcon | Whether to show icon | boolean | false, in `banner` mode default is true |
|
||||
| type | Type of Alert styles, options: `success`, `info`, `warning`, `error` | string | `info`, in `banner` mode default is `warning` |
|
||||
| onClose | Callback when Alert is closed | (e: MouseEvent) => void | - |
|
||||
|
||||
### Alert.ErrorBoundary
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| ----------- | -------------------------------- | --------- | ------------------- | ------- |
|
||||
| message | custom error message to show | ReactNode | `{{ error }}` | |
|
||||
| description | custom error description to show | ReactNode | `{{ error stack }}` | |
|
||||
|
@ -16,6 +16,7 @@ import classNames from 'classnames';
|
||||
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import getDataOrAriaProps from '../_util/getDataOrAriaProps';
|
||||
import ErrorBoundary from './ErrorBoundary';
|
||||
|
||||
function noop() {}
|
||||
|
||||
@ -65,6 +66,8 @@ const iconMapOutlined = {
|
||||
};
|
||||
|
||||
export default class Alert extends React.Component<AlertProps, AlertState> {
|
||||
static ErrorBoundary = ErrorBoundary;
|
||||
|
||||
state = {
|
||||
closing: false,
|
||||
closed: false,
|
||||
|
@ -26,3 +26,10 @@ title: Alert
|
||||
| showIcon | 是否显示辅助图标 | boolean | false,`banner` 模式下默认值为 true |
|
||||
| type | 指定警告提示的样式,有四种选择 `success`、`info`、`warning`、`error` | string | `info`,`banner` 模式下默认值为 `warning` |
|
||||
| onClose | 关闭时触发的回调函数 | (e: MouseEvent) => void | 无 |
|
||||
|
||||
### Alert.ErrorBoundary
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| message | 自定义错误标题,如果未指定会展示原生报错信息 | ReactNode | `{{ error }}` | |
|
||||
| description | 自定义错误内容,如果未指定会展示报错堆栈 | ReactNode | `{{ error stack }}` | |
|
||||
|
@ -63,9 +63,14 @@
|
||||
&-error {
|
||||
background-color: @alert-error-bg-color;
|
||||
border: @border-width-base @border-style-base @alert-error-border-color;
|
||||
|
||||
.@{alert-prefix-cls}-icon {
|
||||
color: @alert-error-icon-color;
|
||||
}
|
||||
|
||||
.@{alert-prefix-cls}-description {
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
&-close-icon {
|
||||
|
@ -5,14 +5,15 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import classNames from 'classnames';
|
||||
import LZString from 'lz-string';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Tooltip, Alert } from 'antd';
|
||||
import { SnippetsOutlined, CheckOutlined, ThunderboltOutlined } from '@ant-design/icons';
|
||||
import stackblitzSdk from '@stackblitz/sdk';
|
||||
import CodePreview from './CodePreview';
|
||||
import EditButton from '../EditButton';
|
||||
import ErrorBoundary from '../ErrorBoundary';
|
||||
import BrowserFrame from '../../BrowserFrame';
|
||||
|
||||
const { ErrorBoundary } = Alert;
|
||||
|
||||
function compress(string) {
|
||||
return LZString.compressToBase64(string)
|
||||
.replace(/\+/g, '-') // Convert '+' to '-'
|
||||
|
@ -1,22 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Alert } from 'antd';
|
||||
|
||||
export default class ErrorBoundary extends React.Component {
|
||||
state = {
|
||||
error: null,
|
||||
};
|
||||
|
||||
componentDidCatch(error, info) {
|
||||
this.setState({ error, info });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { error, info } = this.state;
|
||||
if (error) {
|
||||
// You can render any custom fallback UI
|
||||
return <Alert type="error" message={error.toString()} description={info.componentStack} />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user