fix(issues): stop cold-load render loop on the Issues route (MUL-4985)#5643
Merged
Conversation
Board and Swimlane crashed with "Maximum update depth exceeded" on first paint of the Issues route. During cold load the member/agent/squad directory queries are unresolved, so useActorName's `= []` defaults allocated a fresh array every render and its `getActorName` memo changed identity each render. BoardView's `groups` (and SwimLaneView's `laneGroups`) list `getActorName` as a dep, so they churned every render and re-fired the column-resync effect without end; react-virtuoso escalated the loop into the reported crash. This predates MUL-4797 — it was exposed when board/swimlane columns were virtualized with a real <Virtuoso>. - Share stable empty references for the loading directory snapshot so getActorName is referentially stable across cold-load renders (root cause). - Equality-guard the shared column setter in useDragSettle so a content-equal rebuild returns the previous reference and cannot spin the resync effect (defense-in-depth). Regression coverage: useActorName stability during cold load; the column-setter equality guard; and Board (40 cards) + Swimlane rendered with the REAL react-virtuoso under pending directories, which reproduce "Maximum update depth exceeded" without the fix and pass with it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
The Issues route crashed with "Maximum update depth exceeded" on first paint (
desktop_route_erroron/…/issues). Root cause is a cold-load reference-instability loop, amplified by the real<Virtuoso>in the Board/Swimlane columns:useActorName'sconst { data: members = [] }defaults allocated a fresh array every render, so itsgetActorNamememo changed identity each render.BoardView'sgroupsmemo andSwimLaneView'slaneGroupslistgetActorNameas a dependency, so they churned a new value every render.useEffect(setColumns, [groups, …])then re-fired without end.react-virtuosorepublishes its store synchronously on every render, which starves the query-resolution microtask and escalates the loop into the reported crash.This is not a MUL-4797 regression — it reproduces at the parent commit and was exposed by the earlier board/swimlane virtualization reland (
ea03912ba) that mounted a real<Virtuoso>; the latentgetActorNameinstability predates that.Changes
packages/core/workspace/hooks.ts: share stable module-level empty arrays for the loading directory snapshot, sogetActorNameis referentially stable across cold-load renders (matches the existingEMPTY_*convention in the surface data hook).packages/views/issues/components/use-drag-settle.ts: equality-guard the shared column setter so a content-equal rebuild returns the previous reference and cannot spin the resync effect from any future unstable input. It only skips no-op writes; drag/settle semantics are unchanged.workspaceProperties = []was considered but left untouched: during cold loadgroupingPropertycollapses to a stablenull, so it does not churn thegroupsmemo.groupsis fully stabilized by fix (1).Verification
packages/core/workspace/hooks.test.tsx—getActorNameis referentially stable across renders during cold load.packages/views/issues/components/use-drag-settle.test.tsx— the column setter does not loop when a resync effect rebuilds a content-equal map every render, and still applies real content changes.packages/views/issues/components/issues-cold-load-loop.test.tsx— Board (40 cards → real<Virtuoso>) and Swimlane (assignee grouping) render under pending directory queries with the realreact-virtuoso. Without the fix the Board test fails with the exact issue error ("Maximum update depth exceeded"); with the fix both paint.packages/viewsissues tests 417 passed (incl. the 40+ swimlane drag tests exercising the guarded setter);packages/coreworkspace tests 19 passed.tsc --noEmitclean andeslintclean forpackages/coreandpackages/views.Closes MUL-4985