From 7262b34ae947abc13a8264850a38208dc0daaaaa Mon Sep 17 00:00:00 2001 From: Gulum Date: Tue, 23 Jun 2026 13:52:16 +0200 Subject: [PATCH] =?UTF-8?q?fix(ux):=20Scrollposition=20=C3=BCbersteht=20au?= =?UTF-8?q?ch=20Dev-Server-Hot-Reload=20(Vite=20HMR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../src/hooks/useScrollRestoration.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/gerbil-manager-web/src/hooks/useScrollRestoration.ts b/gerbil-manager-web/src/hooks/useScrollRestoration.ts index cc8d5d4..26b677f 100644 --- a/gerbil-manager-web/src/hooks/useScrollRestoration.ts +++ b/gerbil-manager-web/src/hooks/useScrollRestoration.ts @@ -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]) }