fix(chat): set scroll position before paint on session-switch replay (#1730)

Replace useEffect with useLayoutEffect in the pendingInitialRestoreRef
replay so restoreSnapshot runs synchronously after DOM commit, before
the browser paints. Prevents visible flash of content at the wrong
scroll position when the scroll container mounts after session
hydration.

Adapted from openchamber/openchamber#1553 (Fix 2). The virtualVersion
counter (Fix 1) is not applicable: virtua (post #1651) does not use
useVirtualizer's useState-based instance pattern that motivated it.

Validation:
- bun --cwd packages/ui type-check - no new errors in useChatAutoFollow.ts
- bun --cwd packages/ui lint - passed

Co-authored-by: herjarsa <herjarsa@users.noreply.github.com>
This commit is contained in:
Hernan Javier Ardila Sanchez
2026-06-24 17:28:46 +03:00
committed by GitHub
co-authored by herjarsa
parent 1558364b49
commit 1abb0dc103
+3 -1
View File
@@ -411,7 +411,9 @@ export const useChatAutoFollow = ({
}, [sessionIsWorking, startFollowLoop]);
// Replay a deferred restoreSnapshot once ChatViewport mounts.
React.useEffect(() => {
// useLayoutEffect ensures scroll position is set before the browser paints,
// preventing a visible flash of content at the wrong scroll position.
React.useLayoutEffect(() => {
if (!containerEl) return;
if (pendingInitialRestoreRef.current && pendingInitialRestoreRef.current === currentSessionId) {
void restoreSnapshot();