diff --git a/packages/ui/src/components/chat/MessageList.tsx b/packages/ui/src/components/chat/MessageList.tsx index 0ae15742..cc3d58fa 100644 --- a/packages/ui/src/components/chat/MessageList.tsx +++ b/packages/ui/src/components/chat/MessageList.tsx @@ -1372,8 +1372,6 @@ const MessageList = React.forwardRef(({ scrollEl.scrollTop += prependedHeight; }); - const [historyVirtualRows, setHistoryVirtualRows] = React.useState(EMPTY_VIRTUAL_ROWS); - const historyVirtualizer = useVirtualizer({ count: historyEntries.length, getScrollElement: resolveScrollContainer, @@ -1383,9 +1381,6 @@ const MessageList = React.forwardRef(({ useAnimationFrameWithResizeObserver: true, overscan: MESSAGE_LIST_OVERSCAN, enabled: shouldVirtualizeHistory, - onChange: () => { - setHistoryVirtualRows(historyVirtualizer.getVirtualItems()); - }, }); React.useLayoutEffect(() => { @@ -1440,13 +1435,10 @@ const MessageList = React.forwardRef(({ }; }, []); - // Sync virtual rows on initial mount and when virtualization toggles. - // Ongoing updates are handled by the virtualizer's onChange callback. - React.useLayoutEffect(() => { - setHistoryVirtualRows( - shouldVirtualizeHistory ? historyVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ROWS, - ); - }, [shouldVirtualizeHistory, historyVirtualizer]); + const historyVirtualRows = React.useMemo( + () => (shouldVirtualizeHistory ? historyVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ROWS), + [historyVirtualizer, shouldVirtualizeHistory], + ); const allEntries = React.useMemo(() => { return trailingStreamingEntry ? [...historyEntries, trailingStreamingEntry] : historyEntries; diff --git a/packages/ui/src/hooks/useChatAutoFollow.ts b/packages/ui/src/hooks/useChatAutoFollow.ts index 7b37e272..59c281bd 100644 --- a/packages/ui/src/hooks/useChatAutoFollow.ts +++ b/packages/ui/src/hooks/useChatAutoFollow.ts @@ -411,9 +411,7 @@ export const useChatAutoFollow = ({ }, [sessionIsWorking, startFollowLoop]); // Replay a deferred restoreSnapshot once ChatViewport mounts. - // useLayoutEffect ensures scroll position is set before the browser paints, - // preventing a visible flash of content at the wrong scroll position. - React.useLayoutEffect(() => { + React.useEffect(() => { if (!containerEl) return; if (pendingInitialRestoreRef.current && pendingInitialRestoreRef.current === currentSessionId) { void restoreSnapshot();