perf: memo CodeBlockViewer, DiffViewer, CompactBoundary

These are the most expensive render components (syntax highlighting, diff
computation) — memoizing them prevents re-renders when parent tool items
toggle expand/collapse or parent chat group updates.
This commit is contained in:
Mike 2026-05-02 22:33:29 +05:00
parent 4c8a093200
commit 49006ee589
3 changed files with 12 additions and 12 deletions

View file

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { memo, useState } from 'react';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import { import {
@ -28,9 +28,9 @@ interface CompactBoundaryProps {
* CompactBoundary displays a horizontal divider indicating where * CompactBoundary displays a horizontal divider indicating where
* the conversation was compacted. Click to expand the compacted summary. * the conversation was compacted. Click to expand the compacted summary.
*/ */
export const CompactBoundary = ({ export const CompactBoundary = memo(function CompactBoundary({
compactGroup, compactGroup,
}: Readonly<CompactBoundaryProps>): React.JSX.Element => { }: Readonly<CompactBoundaryProps>): React.JSX.Element {
const { timestamp, message } = compactGroup; const { timestamp, message } = compactGroup;
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
@ -166,4 +166,4 @@ export const CompactBoundary = ({
)} )}
</div> </div>
); );
}; });

View file

@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react'; import React, { memo, useMemo, useState } from 'react';
import { getBaseName } from '@renderer/utils/pathUtils'; import { getBaseName } from '@renderer/utils/pathUtils';
import { createLogger } from '@shared/utils/logger'; import { createLogger } from '@shared/utils/logger';
@ -117,14 +117,14 @@ function inferLanguage(fileName: string): string {
// Component // Component
// ============================================================================= // =============================================================================
export const CodeBlockViewer: React.FC<CodeBlockViewerProps> = ({ export const CodeBlockViewer = memo(function CodeBlockViewer({
fileName, fileName,
content, content,
language, language,
startLine = 1, startLine = 1,
endLine, endLine,
maxHeight = 'max-h-96', maxHeight = 'max-h-96',
}): React.JSX.Element => { }: CodeBlockViewerProps): React.JSX.Element {
const [isCopied, setIsCopied] = useState(false); const [isCopied, setIsCopied] = useState(false);
// Infer language from file extension if not provided // Infer language from file extension if not provided
@ -241,4 +241,4 @@ export const CodeBlockViewer: React.FC<CodeBlockViewerProps> = ({
</div> </div>
</div> </div>
); );
}; });

View file

@ -1,4 +1,4 @@
import React, { useMemo } from 'react'; import React, { memo, useMemo } from 'react';
import { import {
CODE_BG, CODE_BG,
@ -349,14 +349,14 @@ const DiffLineRow: React.FC<DiffLineRowProps> = ({ line, highlightedHtml }): Rea
// Main Component // Main Component
// ============================================================================= // =============================================================================
export const DiffViewer: React.FC<DiffViewerProps> = ({ export const DiffViewer = memo(function DiffViewer({
fileName, fileName,
oldString, oldString,
newString, newString,
maxHeight = 'max-h-96', maxHeight = 'max-h-96',
tokenCount, tokenCount,
syntaxHighlight = false, syntaxHighlight = false,
}): React.JSX.Element => { }: DiffViewerProps): React.JSX.Element {
// Compute diff // Compute diff
const oldLines = oldString.split(/\r?\n/); const oldLines = oldString.split(/\r?\n/);
const newLines = newString.split(/\r?\n/); const newLines = newString.split(/\r?\n/);
@ -456,4 +456,4 @@ export const DiffViewer: React.FC<DiffViewerProps> = ({
</div> </div>
</div> </div>
); );
}; });