fix: optimize ChatView to prevent excessive re-rendering when typing

- Properly memoized itemContent callback with stable dependencies
- Added memoization for lastModifiedMessage to prevent unnecessary recalculations
- Removed debug logging after confirming the fix works

This fixes the UI jittering issue that occurred when typing in the chat input
by preventing the groupedMessages and itemContent from being recalculated on
every keystroke.
This commit is contained in:
Roo Code 2025-08-26 17:32:42 +00:00
parent a79c3d04a6
commit a9a09759b0
2 changed files with 14 additions and 7 deletions

View file

@ -68,6 +68,7 @@ interface ChatRowContentProps extends Omit<ChatRowProps, "onHeightChange"> {}
const ChatRow = memo(
(props: ChatRowProps) => {
const { isLast, onHeightChange, message } = props
// Store the previous height to compare with the current height
// This allows us to detect changes without causing re-renders
const prevHeightRef = useRef(0)

View file

@ -160,7 +160,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
return getLatestTodo(messages)
}, [messages, currentTaskTodos])
const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])
const modifiedMessages = useMemo(() => {
return combineApiRequests(combineCommandSequences(messages.slice(1)))
}, [messages])
// Has to be after api_req_finished are all reduced into api_req_started messages.
const apiMetrics = useMemo(() => getApiMetrics(modifiedMessages), [modifiedMessages])
@ -1521,6 +1523,10 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
userRespondedRef.current = true
}, [])
// Memoize the last modified message to prevent unnecessary re-renders
const lastModifiedMessage = useMemo(() => modifiedMessages.at(-1), [modifiedMessages])
// Properly memoized itemContent callback with stable dependencies
const itemContent = useCallback(
(index: number, messageOrGroup: ClineMessage | ClineMessage[]) => {
// browser session group
@ -1529,7 +1535,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
<BrowserSessionRow
messages={messageOrGroup}
isLast={index === groupedMessages.length - 1}
lastModifiedMessage={modifiedMessages.at(-1)}
lastModifiedMessage={lastModifiedMessage}
onHeightChange={handleRowHeightChange}
isStreaming={isStreaming}
isExpanded={(messageTs: number) => expandedRows[messageTs] ?? false}
@ -1549,12 +1555,12 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
key={messageOrGroup.ts}
message={messageOrGroup}
isExpanded={expandedRows[messageOrGroup.ts] || false}
onToggleExpand={toggleRowExpansion} // This was already stabilized
lastModifiedMessage={modifiedMessages.at(-1)} // Original direct access
isLast={index === groupedMessages.length - 1} // Original direct access
onToggleExpand={toggleRowExpansion}
lastModifiedMessage={lastModifiedMessage}
isLast={index === groupedMessages.length - 1}
onHeightChange={handleRowHeightChange}
isStreaming={isStreaming}
onSuggestionClick={handleSuggestionClickInRow} // This was already stabilized
onSuggestionClick={handleSuggestionClickInRow}
onBatchFileResponse={handleBatchFileResponse}
onFollowUpUnmount={handleFollowUpUnmount}
isFollowUpAnswered={messageOrGroup.ts === currentFollowUpTs}
@ -1582,7 +1588,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
[
expandedRows,
toggleRowExpansion,
modifiedMessages,
lastModifiedMessage, // Use the memoized value instead of recalculating
groupedMessages.length,
handleRowHeightChange,
isStreaming,