fix(ux): Scrollposition übersteht auch Dev-Server-Hot-Reload (Vite HMR)

Bei einem HMR-/Fast-Refresh-Update rendert die Seite kurz neu (Liste kollabiert →
Sprung nach oben), ohne Navigation/pagehide. Jetzt vor `vite:beforeUpdate`/
`vite:beforeFullReload` sichern und nach `vite:afterUpdate` wiederherstellen (nur Dev;
import.meta.hot ist in Produktion undefiniert). Restore-Fenster auf 4 s erhöht, damit
auch langsam nachladende Listen die Position noch erreichen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 13:52:16 +02:00
parent ebc70cc0b8
commit 7262b34ae9

View File

@@ -15,7 +15,9 @@ import { useCallback, useEffect, useRef } from 'react'
import { useLocation, useNavigationType } from 'react-router-dom'
const PREFIX = 'scroll:'
const RESTORE_DEADLINE_MS = 2500
// Etwas großzügig, damit auch langsam (kalt) nachladende Listen + Dev-HMR-Updates die Position
// noch erreichen, während der Inhalt in die Höhe wächst.
const RESTORE_DEADLINE_MS = 4000
export function useScrollRestoration() {
const { pathname } = useLocation()
@@ -126,4 +128,23 @@ export function useScrollRestoration() {
if (rafSaveRef.current != null) cancelAnimationFrame(rafSaveRef.current)
}
}, [persist, restore])
// NUR Dev (Vite-HMR / React Fast Refresh): bei einem Hot-Update wird die Seite kurz neu
// gerendert (Liste kollabiert → Sprung nach oben), ohne dass eine Navigation oder ein
// pagehide/pageshow feuert. Daher hier explizit vor dem Update sichern und danach
// wiederherstellen. In der Produktion ist import.meta.hot undefiniert → No-Op.
useEffect(() => {
const hot = import.meta.hot
if (!hot) return
const before = () => persist()
const after = () => restore(pathRef.current, false)
hot.on('vite:beforeUpdate', before)
hot.on('vite:afterUpdate', after)
hot.on('vite:beforeFullReload', before)
return () => {
hot.off?.('vite:beforeUpdate', before)
hot.off?.('vite:afterUpdate', after)
hot.off?.('vite:beforeFullReload', before)
}
}, [persist, restore])
}