v1.6: Login-Race behoben (schwarzer Bildschirm nach Anmeldung)
- Store setzt 'me' erst nach dem Laden der Bootstrap-Daten (Start, Login, Registrierung) - vorher rendereten Seiten gegen leere Daten und brachen ab; Seite lief erst nach manuellem Reload (Race zwischen setMe und ladeAlles) - FehlerGrenze (ErrorBoundary) in App.tsx: Render-Fehler zeigen Hinweis + Reload-Button statt schwarzem Bildschirm
This commit is contained in:
+35
-3
@@ -1,4 +1,5 @@
|
|||||||
import { Routes, Route, Navigate } from 'react-router'
|
import { Routes, Route, Navigate } from 'react-router'
|
||||||
|
import { Component, type ReactNode } from 'react'
|
||||||
import { StoreProvider, useStore } from './store/store'
|
import { StoreProvider, useStore } from './store/store'
|
||||||
import AppLayout from './components/AppLayout'
|
import AppLayout from './components/AppLayout'
|
||||||
import Login from './pages/Login'
|
import Login from './pages/Login'
|
||||||
@@ -9,6 +10,35 @@ import Documents from './pages/Documents'
|
|||||||
import Messages from './pages/Messages'
|
import Messages from './pages/Messages'
|
||||||
import BenutzerVerwaltung from './pages/BenutzerVerwaltung'
|
import BenutzerVerwaltung from './pages/BenutzerVerwaltung'
|
||||||
|
|
||||||
|
/** Fängt Render-Fehler ab – statt schwarzem Bildschirm: Hinweis + Reload. */
|
||||||
|
class FehlerGrenze extends Component<{ children: ReactNode }, { fehler: boolean }> {
|
||||||
|
state = { fehler: false }
|
||||||
|
static getDerivedStateFromError() {
|
||||||
|
return { fehler: true }
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
if (this.state.fehler) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center bg-[#22333b] p-6">
|
||||||
|
<div className="max-w-md rounded-2xl bg-white p-8 text-center shadow-2xl dark:bg-slate-900">
|
||||||
|
<h1 className="text-xl font-bold">Da ist etwas schiefgelaufen</h1>
|
||||||
|
<p className="mt-2 text-sm text-slate-500">
|
||||||
|
Die Seite konnte nicht korrekt dargestellt werden. Ein Neuladen hilft in der Regel weiter.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
className="mt-5 rounded-xl bg-amber-500 px-6 py-2.5 font-semibold text-slate-900 hover:bg-amber-400"
|
||||||
|
>
|
||||||
|
Seite neu laden
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return this.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Ladebildschirm() {
|
function Ladebildschirm() {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center bg-[#22333b]">
|
<div className="flex min-h-screen items-center justify-center bg-[#22333b]">
|
||||||
@@ -36,8 +66,9 @@ function LoginGate() {
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<StoreProvider>
|
<FehlerGrenze>
|
||||||
<Routes>
|
<StoreProvider>
|
||||||
|
<Routes>
|
||||||
<Route path="/login" element={<LoginGate />} />
|
<Route path="/login" element={<LoginGate />} />
|
||||||
<Route
|
<Route
|
||||||
element={
|
element={
|
||||||
@@ -55,6 +86,7 @@ export default function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
<Route path="*" element={<Navigate to="/" replace />} />
|
<Route path="*" element={<Navigate to="/" replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</StoreProvider>
|
</StoreProvider>
|
||||||
|
</FehlerGrenze>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -112,9 +112,9 @@ export function StoreProvider({ children }: { children: ReactNode }) {
|
|||||||
;(async () => {
|
;(async () => {
|
||||||
try {
|
try {
|
||||||
const { benutzer } = await apiGet<{ benutzer: Benutzer }>('/api/auth/me')
|
const { benutzer } = await apiGet<{ benutzer: Benutzer }>('/api/auth/me')
|
||||||
|
await ladeAlles() // erst Daten, dann me – sonst rendern Seiten gegen leere Daten
|
||||||
if (!aktiv) return
|
if (!aktiv) return
|
||||||
setMe(benutzer)
|
setMe(benutzer)
|
||||||
await ladeAlles()
|
|
||||||
} catch {
|
} catch {
|
||||||
/* nicht angemeldet – Login-Seite zeigen */
|
/* nicht angemeldet – Login-Seite zeigen */
|
||||||
} finally {
|
} finally {
|
||||||
@@ -148,8 +148,8 @@ export function StoreProvider({ children }: { children: ReactNode }) {
|
|||||||
benutzername,
|
benutzername,
|
||||||
passwortHash: await sha256(passwort),
|
passwortHash: await sha256(passwort),
|
||||||
})
|
})
|
||||||
|
await ladeAlles() // erst Daten, dann me (s. useEffect)
|
||||||
setMe(benutzer)
|
setMe(benutzer)
|
||||||
await ladeAlles()
|
|
||||||
return null
|
return null
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return fehlerNachricht(e)
|
return fehlerNachricht(e)
|
||||||
@@ -173,8 +173,8 @@ export function StoreProvider({ children }: { children: ReactNode }) {
|
|||||||
email,
|
email,
|
||||||
passwortHash: await sha256(passwort),
|
passwortHash: await sha256(passwort),
|
||||||
})
|
})
|
||||||
|
await ladeAlles() // erst Daten, dann me (s. useEffect)
|
||||||
setMe(benutzer)
|
setMe(benutzer)
|
||||||
await ladeAlles()
|
|
||||||
return null
|
return null
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return fehlerNachricht(e)
|
return fehlerNachricht(e)
|
||||||
|
|||||||
Reference in New Issue
Block a user