diff --git a/src/App.tsx b/src/App.tsx index 0f240bb..33b61a1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import JournalPage from './components/JournalPage'; import LedgerPage from './components/LedgerPage'; import BalanceSheetPage from './components/BalanceSheetPage'; import SettingsPage from './components/SettingsPage'; +import { ErrorBoundary } from './components/ErrorBoundary'; export default function App() { const { currentPage } = useStore(); @@ -22,8 +23,12 @@ export default function App() { }; return ( - - {renderPage()} - + + + + {renderPage()} + + + ); } diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..095ef4b --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,46 @@ +import { Component, type ErrorInfo, type ReactNode } from 'react'; + +interface Props { + children: ReactNode; +} + +interface State { + hasError: boolean; + error?: Error; +} + +export class ErrorBoundary extends Component { + constructor(props: Props) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError(error: Error): State { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, info: ErrorInfo) { + console.error('[ErrorBoundary] Caught error:', error, info.componentStack); + } + + render() { + if (this.state.hasError) { + return ( +
+

⚠️

+

エラーが発生しました

+

+ {this.state.error?.message} +

+ +
+ ); + } + return this.props.children; + } +} diff --git a/src/components/ImportPage.tsx b/src/components/ImportPage.tsx index a86a957..94a9bd3 100644 --- a/src/components/ImportPage.tsx +++ b/src/components/ImportPage.tsx @@ -78,7 +78,7 @@ export default function ImportPage() { // 振替としてスキップされた取引(振替=1 のrawRecords) const skippedTransfers = useMemo(() => - rawRecords.filter(r => r.振替 === '1' && r.ID).sort((a, b) => b.日付.localeCompare(a.日付)), + rawRecords.filter(r => r.振替 === '1' && r.ID).sort((a, b) => (b.日付 ?? '').localeCompare(a.日付 ?? '')), [rawRecords] );