错误边界捕获
根据需要选择类组件或者函数组件,二选一即可
类组件
import React from 'react';
// 类组件:实现错误边界的核心逻辑
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
error: null,
errorInfo: null,
};
}
static getDerivedStateFromError(error) {
// 更新 state,使下一次渲染能够显示备用 UI
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// 可以在这里将错误信息上报到错误监控服务
this.setState({
errorInfo,
});
}
render() {
if (this.state.hasError) {
// 渲染降级 UI
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error.toString()}
<br />
{this.state.errorInfo?.componentStack}
</details>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
函数组件
此处以 tsx 为例,若使用的是 jsx,只需要把类型去掉
import React, { useEffect, useState } from 'react';
// 函数组件:实现错误边界的核心逻辑
type ErrorBoundaryProps = {
children: React.ReactNode;
};
const ErrorBoundary: React.FC<ErrorBoundaryProps> = ({ children }) => {
const [hasError, setHasError] = useState<boolean>(false);
const [error, setError] = useState<Error | null>(null);
const [errorInfo, setErrorInfo] = useState<React.ErrorInfo | null>(null);
useEffect(() => {
// 捕获全局错误
const errorHandler = (event: PromiseRejectionEvent | ErrorEvent) => {
setError(event instanceof ErrorEvent ? event.error : event.reason);
setErrorInfo(event instanceof ErrorEvent ? event.errorInfo : null);
setHasError(true);
};
window.addEventListener('error', errorHandler);
window.addEventListener('unhandledrejection', errorHandler);
return () => {
window.removeEventListener('error', errorHandler);
window.removeEventListener('unhandledrejection', errorHandler);
};
}, []);
if (hasError) {
// 渲染降级 UI
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{error.toString()}
<br />
{errorInfo?.componentStack}
</details>
</div>
);
}
return children;
};
export default ErrorBoundary;
主组件
错误边界捕获在主组件中的应用
示例
仅限使用于展示错误边界的捕获效果
import React, { useState } from 'react';
import ErrorBoundary from './ErrorBoundary';
function ChildComponent({ throwError }) {
if (throwError) {
throw new Error('Error from ChildComponent!');
}
return <div>Child Component is working!</div>;
}
export default function App() {
const [throwError, setThrowError] = useState(false);
return (
<div>
<h1>React Error Handling</h1>
<button onClick={() => setThrowError(true)}>Trigger Error</button>
<ErrorBoundary>
<ChildComponent throwError={throwError} />
</ErrorBoundary>
</div>
);
}
实际应用
用 ErrorBoundary 将你原本的代码包住,放置最外层
import React, { useState } from 'react';
import ErrorBoundary from './ErrorBoundary';
export default function App() {
const [throwError, setThrowError] = useState(false);
return (
<ErrorBoundary>
// 你的组件/代码
</ErrorBoundary>
);
}