Skip to content

Fix markdown highlight render stability#2479

Merged
juliusmarminge merged 1 commit intomainfrom
cursor/react-performance-scan-c17d
May 4, 2026
Merged

Fix markdown highlight render stability#2479
juliusmarminge merged 1 commit intomainfrom
cursor/react-performance-scan-c17d

Conversation

@cursor
Copy link
Copy Markdown
Contributor

@cursor cursor Bot commented May 3, 2026

What Changed

  • Split the uncached Shiki highlighting path out of SuspenseShikiCodeBlock so cached-highlight renders no longer skip hooks.
  • Hoisted static MessagesTimeline LegendList header/footer elements to avoid passing fresh element props on every render.

Why

react-doctor flagged two hook-order errors in ChatMarkdown.tsx caused by returning cached highlighted HTML before calling use()/useMemo()/useEffect(). This is both a correctness issue and a render hot path for assistant markdown/code blocks. The split keeps hook order stable while preserving the highlight cache. The timeline hoist removes avoidable prop churn in the virtualized message list.

Scan evidence:

  • Before react-doctor: 75/100, 2 errors (ChatMarkdown.tsx hook-order violations).
  • After react-doctor: 76/100, 0 errors.
  • React Scan headless benchmark after fix: completed with totalEvents: 113, commits: 24, timelineRowFibers: 22.
  • React Scan benchmark against the previous implementation did not complete the cached-code scenario, matching the hook-order failure identified by React Doctor.

UI Changes

No intentional 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
Open in Web View Automation 

Note

Fix markdown highlight render stability by extracting UncachedShikiCodeBlock component

  • Extracts the uncached code highlighting path in ChatMarkdown.tsx into a new UncachedShikiCodeBlock component, isolating the use() call for the highlighter promise to prevent render instability.
  • Stabilizes ListHeaderComponent and ListFooterComponent in MessagesTimeline.tsx by replacing inline JSX with module-level constants TIMELINE_LIST_HEADER and TIMELINE_LIST_FOOTER, avoiding unnecessary re-renders from new object references on each render.

Macroscope summarized b3a7b9d.


Note

Low Risk
Low risk UI render-path refactor that preserves behavior while fixing React hook-order stability and reducing avoidable re-renders; main risk is subtle regressions in code highlighting/caching.

Overview
Fixes a React hook-order issue in markdown code highlighting by extracting the uncached Shiki path into UncachedShikiCodeBlock, so cached-highlight renders no longer bypass use()/useMemo()/useEffect().

Reduces render churn in MessagesTimeline by hoisting static LegendList header/footer elements into module-level constants instead of creating new JSX elements each render.

Reviewed by Cursor Bugbot for commit b3a7b9d. 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 size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels May 3, 2026
@juliusmarminge juliusmarminge marked this pull request as ready for review May 3, 2026 23:05
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 3, 2026

Approvability

Verdict: Approved

Pure React render stability optimizations - extracting a component and hoisting inline JSX to constants. No runtime behavior changes, just standard performance patterns to prevent unnecessary re-renders.

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

@juliusmarminge juliusmarminge merged commit 623e471 into main May 4, 2026
16 checks passed
@juliusmarminge juliusmarminge deleted the cursor/react-performance-scan-c17d branch May 4, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 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.

2 participants