Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / frontend/src/components/ErrorBoundary.tsx |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | frontend/src/components/ErrorBoundary.tsx |
| Original SHA-256 | 2c75803336d3e2d6ea485f7ee619394c1cfa942a6145f953f917c0f361084ca1 |
| Git blob SHA | 144f4884afd09d539649475a4bfd9105fb8d8ddb |
| Reading-copy SHA-256 | 2c75803336d3e2d6ea485f7ee619394c1cfa942a6145f953f917c0f361084ca1 |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / frontend/src/components/ErrorBoundary.tsx | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / frontend/src/components/ErrorBoundary.tsx | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓67 lines · 3.0 KB
import { Component, type ErrorInfo, type ReactNode } from 'react'
// The last line of defence for a render throw.
//
// React unmounts the whole tree when a render throws and nothing catches it, so a single bad
// dereference anywhere produced a permanently blank page: no message, no navigation, no way back except
// reloading, and nothing on screen saying a reload would help. That is not a hypothetical here. Go
// marshals a nil slice as JSON `null`, none of the Command Center DTO fields carry omitempty, and several
// screens map straight over those arrays, so an organization with no opportunities is enough to throw.
//
// This is deliberately a class component: error boundaries have no hook equivalent, getDerivedStateFromError
// and componentDidCatch are the only React API for catching a descendant's render error.
type Props = { children: ReactNode }
type State = { error: Error | null }
export class ErrorBoundary extends Component<Props, State> {
state: State = { error: null }
static getDerivedStateFromError(error: Error): State {
return { error }
}
componentDidCatch(error: Error, info: ErrorInfo) {
// Logged rather than swallowed, so the stack survives in the console for whoever is diagnosing it.
// There is no error reporting transport yet; when one exists this is the single place to attach it.
console.error('missionMATCH: unhandled render error', error, info.componentStack)
}
private reset = () => this.setState({ error: null })
render() {
if (!this.state.error) return this.props.children
return (
<div className="grid min-h-screen place-items-center bg-navy-950 p-6">
<div className="w-full max-w-lg space-y-4 rounded-xl border border-line/70 bg-navy-900/60 p-6 text-center">
<p className="text-base font-bold text-ink">Something broke on this screen.</p>
<p className="text-xs text-faint">
The rest of the application is still running. Your work was not lost: nothing is saved from
this screen until you submit it.
</p>
<pre className="max-h-32 overflow-auto rounded-lg border border-line/60 bg-navy-950 p-3 text-left text-[11px] text-muted">
{this.state.error.message}
</pre>
<div className="flex justify-center gap-2">
{/* Try again re mounts the subtree, which recovers from a transient failure without losing the
session. Go home is the escape hatch when the screen itself is the problem. */}
<button
onClick={this.reset}
className="rounded-lg border border-line/70 px-3 py-2 text-sm font-semibold text-muted hover:text-ink"
>
Try again
</button>
<button
onClick={() => {
window.location.href = '/'
}}
className="rounded-lg bg-gradient-to-r from-blue to-navy-700 px-4 py-2 text-sm font-bold text-white hover:brightness-110"
>
Go home
</button>
</div>
</div>
</div>
)
}
}