Skip to content

Commit 352bb8b

Browse files
perf(web): the command output panel compiles without manual memoization
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent a702563 commit 352bb8b

1 file changed

Lines changed: 9 additions & 5 deletions

File tree

‎apps/web/src/components/chat/CommandOutputPanel.tsx‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { EnvironmentId, ThreadId, TurnItemId } from "@t3tools/contracts";
22
import { TERMINAL_PALETTES, terminalOutputSpans } from "@t3tools/shared/terminalOutput";
3-
import { useLayoutEffect, useMemo, useRef } from "react";
3+
import { useLayoutEffect, useRef } from "react";
44

55
import { useTheme } from "../../hooks/useTheme";
66
import { useServerConfigs } from "../../state/entities";
@@ -22,6 +22,13 @@ export function useCommandOutputStreaming(environmentId: EnvironmentId): boolean
2222
* shows its final output. Mount it only when `useCommandOutputStreaming` holds.
2323
* It subscribes only while mounted, so collapsed rows and other threads receive nothing.
2424
*/
25+
// Parsing ANSI output is linear in its length, and the compiler would redo it on
26+
// every render because the layout effect runs after it.
27+
function useTerminalOutputSpans(text: string, resolvedTheme: keyof typeof TERMINAL_PALETTES) {
28+
"use memo";
29+
return terminalOutputSpans(text, TERMINAL_PALETTES[resolvedTheme]);
30+
}
31+
2532
export function CommandOutputPanel(props: {
2633
readonly environmentId: EnvironmentId;
2734
readonly threadId: ThreadId;
@@ -38,10 +45,7 @@ export function CommandOutputPanel(props: {
3845
const followRef = useRef(true);
3946
const text = data?.output.text ?? "";
4047
const { resolvedTheme } = useTheme();
41-
const spans = useMemo(
42-
() => terminalOutputSpans(text, TERMINAL_PALETTES[resolvedTheme]),
43-
[text, resolvedTheme],
44-
);
48+
const spans = useTerminalOutputSpans(text, resolvedTheme);
4549

4650
// This panel only re-renders when its output changes, so keep the end in view after each.
4751
useLayoutEffect(() => {

0 commit comments

Comments
 (0)