"use client"; /** * 全局错误边界组件 * * - 捕获子树中的 React 渲染错误,防止整个页面白屏 * - 在开发环境输出详细错误栈到 console * - 预留 Sentry 集成点(已集成) * - 提供可重置的友好错误 UI */ import React, { Component, ErrorInfo, ReactNode } from "react"; interface Props { children: ReactNode; /** 自定义 fallback UI;不传则使用内置样式 */ fallback?: ReactNode; } interface State { hasError: boolean; error: Error | null; errorInfo: ErrorInfo | null; } export class ErrorBoundary extends Component { constructor(props: Props) { super(props); this.state = { hasError: false, error: null, errorInfo: null }; } static getDerivedStateFromError(error: Error): Partial { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: ErrorInfo): void { this.setState({ errorInfo }); // 开发环境:完整错误栈 if (process.env.NODE_ENV !== "production") { console.group("[ErrorBoundary] 捕获到未处理的渲染错误"); console.error("Error:", error); console.error("Component Stack:", errorInfo.componentStack); console.groupEnd(); } else { console.error("[ErrorBoundary]", error.message); } // Sentry 错误上报(DSN 未配置时自动禁用) try { import("@sentry/nextjs").then((Sentry) => { Sentry.captureException(error, { extra: { componentStack: errorInfo.componentStack } }); }); } catch { // Sentry 未安装或未配置,静默忽略 } } handleReset = (): void => { this.setState({ hasError: false, error: null, errorInfo: null }); }; render(): ReactNode { if (!this.state.hasError) { return this.props.children; } // 使用自定义 fallback if (this.props.fallback) { return this.props.fallback; } // 内置友好错误页面 return (
{/* 图标 */}

页面出现了错误

应用遇到了一个意外错误。您可以尝试刷新页面,或点击下方按钮重试。

{/* 开发环境:展示错误摘要 */} {process.env.NODE_ENV !== "production" && this.state.error && (
错误详情(开发模式)
                {this.state.error.message}
                {this.state.errorInfo?.componentStack}
              
)}
); } } export default ErrorBoundary;