companion-app: Fehlergrenze um die App - Absturz sichtbar statt schwarzer Seite
Ohne React-Error-Boundary unmountet ein unbehandelter Renderfehler die gesamte App; übrig bleibt nur der Seitenhintergrund (im Nacht-Theme praktisch schwarz) - passt zum gemeldeten "schwarze Seite nach Update prüfen". Behebt nicht die eigentliche Ursache, macht einen künftigen Absturz aber sichtbar (Fehlertext, Neu-laden-Knopf) und loggt ihn in die Konsole statt ihn stumm verschwinden zu lassen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Auffangnetz für Abstürze irgendwo im Baum.
|
||||
*
|
||||
* Ohne diese Grenze unmountet React die gesamte App bei jedem unbehandelten
|
||||
* Fehler beim Rendern - #wurzel bleibt leer, und übrig bleibt nur der
|
||||
* Seitenhintergrund (im Nacht-Theme praktisch schwarz). Genau das wurde als
|
||||
* "schwarze Seite nach Update prüfen" gemeldet: kein hängender Ladezustand,
|
||||
* sondern ein stiller Absturz, dessen eigentliche Fehlermeldung nirgends
|
||||
* ankam. Ein "zurück und wieder rein" half nur, weil das erneute Öffnen den
|
||||
* Baum komplett neu aufbaut und der auslösende Zustand dabei verschwindet.
|
||||
*
|
||||
* Diese Grenze behebt nicht die eigentliche Ursache - sie sorgt nur dafür,
|
||||
* dass ein Absturz ab jetzt sichtbar ist (Fehlertext, Neu-laden-Knopf) statt
|
||||
* unsichtbar zu bleiben, und dass der Fehlertext in der Konsole landet, um
|
||||
* die eigentliche Ursache beim nächsten Mal fassen zu können.
|
||||
*/
|
||||
|
||||
import { Component, type ReactNode } from "react"
|
||||
|
||||
import { ActionButton } from "@audi-dash/ui"
|
||||
|
||||
export class ErrorGrenze extends Component<
|
||||
{ children: ReactNode },
|
||||
{ fehler: Error | null }
|
||||
> {
|
||||
state: { fehler: Error | null } = { fehler: null }
|
||||
|
||||
static getDerivedStateFromError(fehler: Error) {
|
||||
return { fehler }
|
||||
}
|
||||
|
||||
componentDidCatch(fehler: Error, info: { componentStack?: string | null }) {
|
||||
console.error("ErrorGrenze: unbehandelter Fehler beim Rendern", fehler, info.componentStack)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.fehler) return this.props.children
|
||||
return (
|
||||
<div className="dm-leer" style={{ minHeight: "100vh", justifyContent: "center" }}>
|
||||
<span className="dm-leer__titel">Etwas ist schiefgelaufen</span>
|
||||
<p className="dm-leer__text">
|
||||
Die Seite konnte nicht dargestellt werden. Ein Neuladen behebt das in der Regel.
|
||||
</p>
|
||||
<p className="dm-leer__text" style={{ fontFamily: "monospace", fontSize: "12px" }}>
|
||||
{this.state.fehler.message}
|
||||
</p>
|
||||
<ActionButton onClick={() => window.location.reload()}>Neu laden</ActionButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import "./stile/grundlage.css"
|
||||
import "./stile/audi-schrift.css"
|
||||
import { nativeAblageEinrichten } from "./api"
|
||||
import { App } from "./App"
|
||||
import { ErrorGrenze } from "./ErrorGrenze"
|
||||
|
||||
// In der nativen Hülle den Token in den Schlüsselbund legen statt in
|
||||
// localStorage. Ohne Hülle passiert hier nichts.
|
||||
@@ -16,6 +17,8 @@ if (!wurzel) throw new Error("Wurzelelement #wurzel fehlt in index.html")
|
||||
|
||||
createRoot(wurzel).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
<ErrorGrenze>
|
||||
<App />
|
||||
</ErrorGrenze>
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user