From 5fefadd37486dda217dd34196746e47b5f66cea0 Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Mon, 13 Apr 2026 12:14:42 -0500 Subject: [PATCH] Memoize PR review file grouping - Cache thread grouping and visible patch files with `useMemo` - Keep the empty dashboard state rendered after derived data setup --- .../src/components/pr-review/PrWorkspace.tsx | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/apps/web/src/components/pr-review/PrWorkspace.tsx b/apps/web/src/components/pr-review/PrWorkspace.tsx index 27417f642..e071f0320 100644 --- a/apps/web/src/components/pr-review/PrWorkspace.tsx +++ b/apps/web/src/components/pr-review/PrWorkspace.tsx @@ -77,36 +77,42 @@ export function PrWorkspace({ [dashboard?.pullRequest.number, patch], ); - if (!dashboard) { - return ( -
- Select a pull request to load the review cockpit. -
- ); - } - - const threadsByPath = dashboard.threads.reduce>( - (acc, thread) => { + const threadsByPath = useMemo>(() => { + if (!dashboard) return {}; + return dashboard.threads.reduce>((acc, thread) => { if (!thread.path) return acc; if (!acc[thread.path]) acc[thread.path] = []; acc[thread.path]!.push(thread); return acc; - }, - {}, + }, {}); + }, [dashboard]); + + const patchFiles = useMemo( + () => (renderablePatch?.kind === "files" ? renderablePatch.files : []), + [renderablePatch], ); - const patchFiles = renderablePatch?.kind === "files" ? renderablePatch.files : []; + const visibleFiles = useMemo( + () => + fileViewMode === "single" && selectedFilePath + ? patchFiles.filter((file) => resolveFileDiffPath(file) === selectedFilePath) + : patchFiles, + [fileViewMode, patchFiles, selectedFilePath], + ); - // In single-file mode, filter to just the selected file - const visibleFiles = - fileViewMode === "single" && selectedFilePath - ? patchFiles.filter((f) => resolveFileDiffPath(f) === selectedFilePath) - : patchFiles; const renderedFiles = useMemo( () => visibleFiles.map(withInferredFileDiffLanguage), [visibleFiles], ); + if (!dashboard) { + return ( +
+ Select a pull request to load the review cockpit. +
+ ); + } + return (
{/* Compact header toolbar — single line */}