fix(desktop): slow session switch (#65890)

react-router v7's HashRouter wraps every route state update in
React.startTransition() by default. In React 19's concurrent renderer,
transitions are non-urgent — React can yield mid-render and come back
later. When the app is under load (streaming token deltas, gateway
events, store updates from active sessions), those higher-priority
updates keep interrupting the transition, starving the route change commit.

This matches every symptom of the session-switch lag:
- Main thread is free (animations run, clicks work) — startTransition
  defers, it does not block
- navigate() does not take effect for seconds — the transition keeps
  getting interrupted by higher-priority updates
- Worse under load — more concurrent re-renders = more interruptions
- The whole UI (sidebar + main pane) does not update — the entire route
  change is one transition, so nothing commits until it finishes

Pass useTransitions={false} to HashRouter so route state updates are
synchronous at default React priority instead of deferred transition
priority. navigate() now commits and paints immediately.

See: react-router v7 chunk-BIP66BKV.js HashRouter implementation.
This commit is contained in:
ethernet 2026-07-16 15:34:53 -04:00 committed by GitHub
parent b0ca12192e
commit f1af945f6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -31,7 +31,16 @@ if (new URLSearchParams(window.location.search).get('win') === 'overlay') {
<I18nProvider>
<ThemeProvider>
<HapticsProvider>
<HashRouter>
{/* useTransitions={false}: react-router v7's HashRouter wraps every
route state update in React.startTransition() by default. In
React 19's concurrent renderer, transitions are non-urgent React
can yield mid-render and resume later. When the app is under load
(streaming token deltas, gateway events, store updates), those
higher-priority updates keep interrupting the transition, starving
the route change commit. The session sidebar highlight + main pane
both freeze for seconds despite the main thread being free.
Disabling transitions makes navigate() commit at default priority. */}
<HashRouter useTransitions={false}>
<App />
</HashRouter>
</HapticsProvider>