From 9b0fd813c3d75f0b56155f797491369808bd6ce7 Mon Sep 17 00:00:00 2001 From: you Date: Thu, 18 Jun 2026 19:56:49 +0900 Subject: [PATCH] =?UTF-8?q?ErrorBoundary=E8=BF=BD=E5=8A=A0:=20=E3=82=A2?= =?UTF-8?q?=E3=83=97=E3=83=AA=E5=85=A8=E4=BD=93=E3=81=AE=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E3=83=8F=E3=83=B3=E3=83=89=E3=83=AA=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E5=BC=B7=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ErrorBoundaryコンポーネントを新規作成(App全体・ページ個別の二重ガード) - ImportPage: 日付フィールドのundefined時にlocaleCompareが落ちる問題を修正 Co-Authored-By: Claude Sonnet 4.6 --- src/App.tsx | 11 +++++--- src/components/ErrorBoundary.tsx | 46 ++++++++++++++++++++++++++++++++ src/components/ImportPage.tsx | 2 +- 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/components/ErrorBoundary.tsx 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] );