ErrorBoundary追加: アプリ全体のエラーハンドリング強化

- ErrorBoundaryコンポーネントを新規作成(App全体・ページ個別の二重ガード)
- ImportPage: 日付フィールドのundefined時にlocaleCompareが落ちる問題を修正

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
you
2026-06-18 19:56:49 +09:00
parent a6ed362106
commit 9b0fd813c3
3 changed files with 55 additions and 4 deletions
+8 -3
View File
@@ -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 (
<Layout>
{renderPage()}
</Layout>
<ErrorBoundary>
<Layout>
<ErrorBoundary>
{renderPage()}
</ErrorBoundary>
</Layout>
</ErrorBoundary>
);
}
+46
View File
@@ -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<Props, State> {
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 (
<div className="flex flex-col items-center justify-center h-screen text-slate-400 p-8 bg-slate-900">
<p className="text-5xl mb-4"></p>
<p className="text-lg font-semibold text-slate-300 mb-2"></p>
<p className="text-sm text-slate-500 mb-6 max-w-md text-center break-all">
{this.state.error?.message}
</p>
<button
onClick={() => this.setState({ hasError: false })}
className="px-4 py-2 bg-indigo-600 text-white rounded-md text-sm hover:bg-indigo-700"
>
</button>
</div>
);
}
return this.props.children;
}
}
+1 -1
View File
@@ -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]
);