fix(web): prevent infinite re-render loop in Sidebar (React error #185)#20
Conversation
The useEffect that calls setExpandedThreadListsByProject fires on every standardProjects reference change. During active LLM chat, SSE events cause sidebarThreadSummaryById to update frequently, which cascades through sortProjectsForSidebar (always creates a new array) to standardProjects (filter, also always new), triggering the effect on every streaming update. The prune function itself returns the same Set reference when no pruning is needed, but the setState call still schedules a render. Under rapid SSE events this exceeds React 19's nested update limit, producing minified error #185 (Maximum update depth exceeded). Fix: track the previous project cwd->expanded mapping in a ref. Only call setExpandedThreadListsByProject when a project's expanded status has actually changed, not just when the standardProjects array got a new reference.
|
Warning Review limit reached
More reviews will be available in 4 minutes and 3 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
React minified error #185 ("Maximum update depth exceeded") crashes the web app during active LLM chat, showing the "Something went wrong" error boundary and requiring constant reloads.
Root Cause
A
useEffectinSidebar.tsxdepends onstandardProjects, which gets a new array reference on every store update during active chat. The dependency chain:sidebarThreadSummaryByIdcreateSidebarThreadSummariesSelectorproduces newsidebarThreadssortProjectsForSidebaralways returns a new array ([...projects].toSorted(...))standardProjects = sortedProjects.filter(...)— also always newuseEffectfires and callssetExpandedThreadListsByProjectunconditionallyEven though
pruneExpandedProjectThreadListsForCollapsedProjectsreturns the same Set reference when no pruning is needed, thesetStatecall still schedules a render. Under rapid SSE events during streaming, this exceeds React 19's nested update limit.Note: React 19 issue #36423 —
NESTED_PASSIVE_UPDATE_LIMITis__DEV__-only, so in production the loop runs silently rather than throwing early.Fix
Add a
useRef<ReadonlyMap<string, boolean>>that tracks the previouscwd -> expandedmapping for projects. TheuseEffectnow compares the current mapping against the previous one and skipssetExpandedThreadListsByProjectwhen no project's expanded status actually changed — only when the reference changed due to unrelated store updates.Testing
n&&snip Je(e=>Vgt({...})))