feat: 增加自定义组件ErrorBoundary, 以及给现有的三个自定义组件,进行错误边界处理 (#501) fix #497

Reviewed-on: daoyoucloud/tachycode#501
Reviewed-by: sealday <zhanglin@daoyoucloud.com>
Co-authored-by: bai.jingfeng <bai.jingfeng@foxmail.com>
Co-committed-by: bai.jingfeng <bai.jingfeng@foxmail.com>
This commit is contained in:
bai.jingfeng 2024-03-26 20:07:25 +08:00 committed by sealday
parent 31ab773e4c
commit f2ad0534fa
6 changed files with 68 additions and 26 deletions

View File

@ -1,16 +1,19 @@
import { SchemaComponent } from '@nocobase/client';
import React from 'react';
import { ErrorBoundary } from './ErrorBoundary';
export const CustomAssociatedField = (props) => {
if (!props.component) return;
return (
<SchemaComponent
schema={{
type: 'string',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
<ErrorBoundary>
<SchemaComponent
schema={{
type: 'string',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
</ErrorBoundary>
);
};

View File

@ -5,6 +5,7 @@ import { useField, useFieldSchema } from '@formily/react';
import { Field } from '@nocobase/database';
import { useCustomComponent } from '../../hooks/useCustomComponent';
import { CustomComponentType } from './custom-components';
import { ErrorBoundary } from './ErrorBoundary';
export const CustomComponentStub = (props) => {
return <div></div>;
@ -13,14 +14,16 @@ export const CustomComponentStub = (props) => {
export const CustomComponentDispatcher = (props) => {
if (!props.component) return;
return (
<SchemaComponent
schema={{
type: 'void',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
<ErrorBoundary>
<SchemaComponent
schema={{
type: 'void',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
</ErrorBoundary>
);
};

View File

@ -1,16 +1,19 @@
import { SchemaComponent } from '@nocobase/client';
import React from 'react';
import { ErrorBoundary } from './ErrorBoundary';
export const CustomField = (props) => {
if (!props.component) return;
return (
<SchemaComponent
schema={{
type: 'string',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
<ErrorBoundary>
<SchemaComponent
schema={{
type: 'string',
name: props.component,
'x-component': props.component,
'x-component-props': props,
}}
/>
</ErrorBoundary>
);
};

View File

@ -0,0 +1,31 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from '../../locale';
export const ErrorBoundary = ({ children, fallback }) => {
const { t } = useTranslation();
const [hasError, setHasError] = useState(false);
useEffect(() => {
// 捕获子组件的错误
const handleError = (error) => {
console.error('Error caught by ErrorBoundary:', error);
setHasError(true);
};
// TODO: 或者上报至错误服务器,记录
// 添加错误处理函数到 window
window.addEventListener('error', handleError);
// 移除事件监听器
return () => {
window.removeEventListener('error', handleError);
};
}, []);
// 如果有错误,展示备用, 可以通过fallback回调自定义,或者显示默认 UI 组件
if (hasError) {
return fallback ? fallback : <div>{t('Something went wrong. Please try again later.')}</div>;
}
// 否则渲染子组件
return children;
};

View File

@ -18,5 +18,6 @@
"Pick a data entry for viewing and editing": "Pick a data entry for viewing and editing",
"Please select": "Please select",
"Association field": "Association field",
"HomePage Config": "HomePage Config"
"HomePage Config": "HomePage Config",
"Something went wrong. Please try again later.": "Something went wrong. Please try again later."
}

View File

@ -18,5 +18,6 @@
"Pick a data entry for viewing and editing": "选择一条数据用于查看与编辑",
"Please select": "请选择",
"Association field": "关联字段",
"HomePage Config": "主页配置"
"HomePage Config": "主页配置",
"Something went wrong. Please try again later.": "系统内部显示错误,请稍后再试"
}