Keep scrollTo's Promise out of the route-change effect

Chrome's window.scrollTo now returns a Promise. The effect that opens
each page at the top returned it, so React kept it as the cleanup and
called it on the next route change: "TypeError: Z is not a function",
which unmounted the whole app until a reload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Iqbal
2026-10-30 10:25:59 +07:00
parent 4e1bee4503
commit 7a51f35ec4

View File

@@ -144,9 +144,11 @@ export function AppLayout() {
const current = NAV.find(n => pathname.startsWith(n.to))
// Nav groups stay closed unless they hold the current page; a click on the label overrides that until the next route.
const [toggled, setToggled] = useState<Partial<Record<Key, boolean>>>({})
useEffect(() => setToggled({}), [pathname])
useEffect(() => { setToggled({}) }, [pathname])
// The window scrolls, not <main>, so a new page would open at the last page's scroll position.
useLayoutEffect(() => window.scrollTo(0, 0), [pathname])
// In braces: Chrome's scrollTo now returns a Promise, which React would keep as the effect's
// cleanup and call on the next route change ("is not a function"), unmounting the whole app.
useLayoutEffect(() => { window.scrollTo(0, 0) }, [pathname])
const [collapsed, setCollapsed] = useState(readCollapsed)
const toggleCollapsed = () => setCollapsed(c => {
try { localStorage.setItem(COLLAPSED_KEY, c ? '0' : '1') } catch { /* keep it for this visit only */ }