From 0ba6f7e83a876f36b80cb571cae1971bd8165603 Mon Sep 17 00:00:00 2001 From: Psyborgs-git <49641518+Psyborgs-git@users.noreply.github.com> Date: Mon, 2 Mar 2026 23:35:19 +0000 Subject: [PATCH] perf(web-ui): optimize ChatMessageItem re-renders with React.memo Implemented React.memo with a custom equality function on ChatMessageItem to prevent unnecessary re-renders of older chat messages when new chunks are streaming in. This dramatically improves UI performance for long chat sessions. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- .../src/components/ai/chat/ChatMessageItem.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/web-ui/src/components/ai/chat/ChatMessageItem.tsx b/packages/web-ui/src/components/ai/chat/ChatMessageItem.tsx index 9e91f45..1790848 100644 --- a/packages/web-ui/src/components/ai/chat/ChatMessageItem.tsx +++ b/packages/web-ui/src/components/ai/chat/ChatMessageItem.tsx @@ -1,7 +1,7 @@ import { Box, Avatar, Typography, Paper, Accordion, AccordionSummary, AccordionDetails, Chip, ListItem, CircularProgress, Tooltip, IconButton, Stack, alpha } from '@mui/material'; import { User as UserIcon, Command, Bot, ChevronDown, Wrench, Brain, RotateCcw, GitFork } from 'lucide-react'; import { ChatMessage } from './types.js'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, memo } from 'react'; import { ChatMessageRenderer } from './ChatMessageRenderer.js'; interface ChatMessageItemProps { @@ -12,7 +12,7 @@ interface ChatMessageItemProps { isGrouped: boolean; } -export function ChatMessageItem({ msg, onRerun, onFork, disabledActions = false, isGrouped = false }: ChatMessageItemProps) { +function ChatMessageItemComponent({ msg, onRerun, onFork, disabledActions = false, isGrouped = false }: ChatMessageItemProps) { const [isThinkingExpanded, setIsThinkingExpanded] = useState(true); const [isHovered, setIsHovered] = useState(false); @@ -249,3 +249,16 @@ export function ChatMessageItem({ msg, onRerun, onFork, disabledActions = false, ); } + +export const ChatMessageItem = memo(ChatMessageItemComponent, (prevProps, nextProps) => { + return ( + prevProps.msg.id === nextProps.msg.id && + prevProps.msg.content === nextProps.msg.content && + prevProps.msg.toolCalls === nextProps.msg.toolCalls && + prevProps.msg.toolResults === nextProps.msg.toolResults && + prevProps.disabledActions === nextProps.disabledActions && + prevProps.isGrouped === nextProps.isGrouped && + prevProps.onRerun === nextProps.onRerun && + prevProps.onFork === nextProps.onFork + ); +});