thread-master/frontend/src/components/ErrorBoundary.tsx

51 lines
1.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Component, type ErrorInfo, type ReactNode } from 'react'
type ErrorBoundaryProps = {
children: ReactNode
fallback?: ReactNode
}
type ErrorBoundaryState = {
hasError: boolean
message: string
}
/**
* 攔截子樹的 render 例外,避免單一元件(例如渲染 AI 任意輸出的 IslanderMarkdown
* 出錯就整頁白屏。
*/
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
state: ErrorBoundaryState = { hasError: false, message: '' }
static getDerivedStateFromError(error: unknown): ErrorBoundaryState {
return { hasError: true, message: error instanceof Error ? error.message : '發生未預期錯誤' }
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error('ErrorBoundary caught error:', error, info.componentStack)
}
private handleReset = () => {
this.setState({ hasError: false, message: '' })
}
render() {
if (!this.state.hasError) return this.props.children
if (this.props.fallback) return this.props.fallback
return (
<div className="ac-slot" style={{ padding: '1.5rem', textAlign: 'center' }}>
<p className="text-ink" style={{ marginBottom: '0.75rem' }}>
</p>
<p className="text-subtle" style={{ marginBottom: '1rem', fontSize: 13 }}>
{this.state.message}
</p>
<button type="button" className="ac-btn-secondary" onClick={this.handleReset}>
</button>
</div>
)
}
}