Skip to content

Reduce sidebar selection rerenders#2560

Open
cursor[bot] wants to merge 1 commit intomainfrom
cursor/react-performance-scan-ec73
Open

Reduce sidebar selection rerenders#2560
cursor[bot] wants to merge 1 commit intomainfrom
cursor/react-performance-scan-ec73

Conversation

@cursor
Copy link
Copy Markdown
Contributor

@cursor cursor Bot commented May 6, 2026

What Changed

  • Removed aggregate sidebar selection-size subscriptions from thread rows, project items, and the root sidebar.
  • Switched those interaction-only checks to read the current thread selection store snapshot inside context-menu, project-click, and global mousedown handlers.

Why

React Doctor and a manual pass pointed to Sidebar.tsx as a hot component, and React Scan confirmed sidebar selection updates were fanning out through mounted thread rows. Reading selection presence at interaction time keeps behavior the same while avoiding parent/row rerenders driven only by aggregate selection-size changes.

React Scan recording for two selection updates on five mounted rows:

  • Before: sidebarThreadRowDuration: 9.4ms
  • After: sidebarThreadRowDuration: 2.8ms

UI Changes

No visual UI changes.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Validation:

  • bun fmt
  • bun lint
  • bun typecheck
  • bun x react-doctor@latest . --json --fail-on none --offline
  • React Scan before/after browser recording via temporary react-scan/lite harness
Open in Web View Automation 

Note

Reduce rerenders in sidebar components by reading selection state on demand

Replaces reactive subscriptions to selectedThreadKeys.size and selectedThreadCount in SidebarThreadRow, SidebarProjectItem, and the root Sidebar component with on-demand reads via useThreadSelectionStore.getState().hasSelection(). This means these components no longer re-render when the selection size changes; instead, they query the current state at the moment of user interaction (right-click, project click, or mousedown).

Macroscope summarized 8681a6d.


Note

Low Risk
Low risk performance refactor limited to the sidebar: it changes how selection presence is read (on-demand via getState()), with minimal chance of behavioral regressions in context-menu/clear-selection interactions.

Overview
Reduces sidebar re-renders caused by multi-selection updates by removing subscriptions to aggregate selection size/count in Sidebar.tsx.

Interaction handlers (thread row context menu, project click, and global mousedown clear-selection) now query useThreadSelectionStore.getState().hasSelection() at event time, keeping behavior while avoiding selection-driven re-render fan-out across mounted rows.

Reviewed by Cursor Bugbot for commit 8681a6d. Bugbot is set up for automated code reviews on this repo. Configure here.

Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels May 6, 2026
@juliusmarminge juliusmarminge marked this pull request as ready for review May 6, 2026 17:03
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 6, 2026

Approvability

Verdict: Approved

This is a mechanical performance optimization that replaces reactive Zustand store subscriptions with imperative getState() reads inside callbacks. The underlying logic is unchanged - just avoiding unnecessary component rerenders when selection state changes.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant