Files
certain/web/src/components/ErrorBoundary.jsx
T
GuidoandClaude Opus 4.8 2c795a57c8 feat: Phase 0 – Gerüst (FastAPI+SQLite, Multi-User-Login, React-App-Shell, Deploy)
Grundgerüst für Certain Finance:
- Backend: FastAPI + SQLAlchemy + SQLite, Alembic-Migrationen (Batch-Mode),
  argon2-Passwort-Hashing, server-seitige Sitzungen im Cookie, Erst-Admin,
  Benutzerverwaltung mit Temporär-Passwort, Einstellungen je Benutzer.
- Ein Prozess, ein Port: uvicorn liefert API (/api) und gebautes SPA aus,
  inkl. SPA-Deeplink-Fallback.
- Frontend: React 18 + Vite + JSX, Design-Tokens (Light/Dark), i18n DE/EN,
  Inline-SVG-Icons (keine Emojis), Login, Passwort-ändern, Dashboard-Platzhalter,
  Benutzer- und Einstellungsseiten.
- Deploy: nativer LXC-Installer + Update-Skript (systemd), env-Vorlage, Doku.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 18:27:42 +02:00

75 lines
2.6 KiB
React
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 } from "react";
import Icon from "./Icon";
/**
* Fängt Fehler beim Rendern ab.
*
* Ohne so eine Grenze hängt React den kompletten Baum aus, sobald irgendwo eine
* Ausnahme fliegt – die Seite wird schlagartig weiß und nur ein Neuladen hilft.
* Man sieht dann NICHT, was passiert ist, und kann es folglich auch nicht
* melden. Genau das war hier das Problem.
*
* Die Grenze zeigt deshalb die Meldung selbst an, nicht nur ein „Ups". Wer sie
* einmal sieht, kann sie weitergeben, und dann ist die Ursache in einer Minute
* gefunden statt in einer Stunde.
*
* `bereich` beschreibt, was gekapselt ist – für die Meldung.
*/
export default class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { fehler: null, info: null };
}
static getDerivedStateFromError(fehler) {
return { fehler };
}
componentDidCatch(fehler, info) {
// React schreibt selbst schon in die Konsole; der Komponentenpfad hilft
// zusätzlich beim Einordnen.
console.error("Fehler beim Rendern:", fehler, info?.componentStack);
this.setState({ info });
}
render() {
const { fehler, info } = this.state;
if (!fehler) return this.props.children;
return (
<div style={{ padding: "var(--sp-4)" }}>
<div className="alert error" style={{ alignItems: "flex-start" }}>
<Icon name="alert" size={16} />
<div style={{ minWidth: 0 }}>
<div className="strong">
{this.props.bereich ? `${this.props.bereich} konnte nicht angezeigt werden.` : "Etwas ist schiefgelaufen."}
</div>
<div className="small" style={{ marginTop: 4, wordBreak: "break-word" }}>
{fehler.message || String(fehler)}
</div>
</div>
</div>
<div className="field-inline" style={{ marginTop: "var(--sp-3)" }}>
<button className="btn primary" onClick={() => this.setState({ fehler: null, info: null })}>
Nochmal versuchen
</button>
<button className="btn" onClick={() => window.location.reload()}>
Seite neu laden
</button>
</div>
{/* Aufgeklappt nur auf Wunsch: die Angaben sind für einen Fehlerbericht
gedacht, nicht für den Alltag. */}
<details style={{ marginTop: "var(--sp-3)" }}>
<summary className="muted small">Technische Angaben</summary>
<pre className="muted small" style={{ whiteSpace: "pre-wrap", overflowX: "auto" }}>
{fehler.stack || String(fehler)}
{info?.componentStack || ""}
</pre>
</details>
</div>
);
}
}