Problem
ReviewState is a single monolithic context with ~40 dependencies in its useMemo. When ANY state changes, ALL useReviewState() consumers re-render — including panels that don't use the changed data.
During active agent reviews, this causes unnecessary re-renders of diff panels, PR panels, and the sidebar every time job state updates, annotation changes, or search state changes.
Current state
jobLogs was split into a separate JobLogsContext (done)
PRCommentsTab and PRSummaryTab wrapped in React.memo (done)
- But every other panel (
ReviewDiffPanel, ReviewPRChecksPanel, etc.) still re-renders on any state change
What's in ReviewState today (all in one context)
- Files & diff:
files, focusedFileIndex, diffStyle, diffOverflow, font settings
- Annotations:
allAnnotations, externalAnnotations, selectedAnnotationId, pendingSelection
- Viewed/staged:
viewedFiles, stagedFiles, stagingFile
- Search:
searchQuery, debouncedSearchQuery, activeSearchMatch, etc.
- AI:
aiMessages, isAILoading, aiHistoryForSelection
- Agent jobs:
agentJobs
- PR:
prMetadata, prContext, platformUser
- Navigation:
openDiffFile
Proposed split
| Context |
Data |
Consumers |
DiffContext |
files, activeFile, diffStyle, search, font |
Diff panels, file tree |
AnnotationContext |
annotations, selection, editing |
Sidebar, diff panels |
AgentContext |
jobs, capabilities |
Agents tab, detail panel |
PRContext |
prMetadata, prContext, platformUser |
PR panels |
JobLogsContext |
jobLogs |
Detail panel (already done) |
Each context only re-renders its consumers when its specific data changes.
Impact
- Eliminates cascading re-renders during agent runs
- Prevents diff panel thrashing when annotations change
- Prevents PR panel re-renders when search state changes
- Follows React best practice: split contexts by update frequency (Dan Abramov's "Before You Memo")
Partial mitigations already in place
JobLogsContext split (high-frequency SSE logs isolated)
React.memo on PRCommentsTab and PRSummaryTab
- Inline
onerror on images (prevents 404 flood even if re-renders happen)
Files involved
packages/review-editor/App.tsx — reviewStateValue useMemo (the monolith)
packages/review-editor/dock/ReviewStateContext.tsx — ReviewState interface
- All files in
packages/review-editor/dock/panels/ — context consumers
packages/review-editor/components/ReviewSidebar.tsx — context consumer
Problem
ReviewStateis a single monolithic context with ~40 dependencies in itsuseMemo. When ANY state changes, ALLuseReviewState()consumers re-render — including panels that don't use the changed data.During active agent reviews, this causes unnecessary re-renders of diff panels, PR panels, and the sidebar every time job state updates, annotation changes, or search state changes.
Current state
jobLogswas split into a separateJobLogsContext(done)PRCommentsTabandPRSummaryTabwrapped inReact.memo(done)ReviewDiffPanel,ReviewPRChecksPanel, etc.) still re-renders on any state changeWhat's in
ReviewStatetoday (all in one context)files,focusedFileIndex,diffStyle,diffOverflow, font settingsallAnnotations,externalAnnotations,selectedAnnotationId,pendingSelectionviewedFiles,stagedFiles,stagingFilesearchQuery,debouncedSearchQuery,activeSearchMatch, etc.aiMessages,isAILoading,aiHistoryForSelectionagentJobsprMetadata,prContext,platformUseropenDiffFileProposed split
DiffContextAnnotationContextAgentContextPRContextJobLogsContextEach context only re-renders its consumers when its specific data changes.
Impact
Partial mitigations already in place
JobLogsContextsplit (high-frequency SSE logs isolated)React.memoonPRCommentsTabandPRSummaryTabonerroron images (prevents 404 flood even if re-renders happen)Files involved
packages/review-editor/App.tsx—reviewStateValueuseMemo (the monolith)packages/review-editor/dock/ReviewStateContext.tsx— ReviewState interfacepackages/review-editor/dock/panels/— context consumerspackages/review-editor/components/ReviewSidebar.tsx— context consumer