Skip to content

fix(deploy-control): stabilize empty deployments selector - #33

Merged
joeylee12629-star merged 1 commit into
nexu-io:mainfrom
cszhouwei:fix/deploy-control-getsnapshot-loop
May 16, 2026
Merged

fix(deploy-control): stabilize empty deployments selector#33
joeylee12629-star merged 1 commit into
nexu-io:mainfrom
cszhouwei:fix/deploy-control-getsnapshot-loop

Conversation

@cszhouwei

Copy link
Copy Markdown
Contributor

Summary

  • DeployControl selector (s) => selectActiveTask(s)?.deployments ?? [] allocated a fresh [] on every render when the active task had no deployments, so zustand's default Object.is snapshot comparison saw a new value each time.
  • That triggered the React warnings getSnapshot should be cached to avoid an infinite loop and Maximum update depth exceeded, surfacing in the preview pane the moment <DeployControl /> mounted for a task without prior deployments.
  • Fix: hoist a module-level EMPTY_DEPLOYMENTS: readonly DeploymentRecord[] constant and return it from the selector so the snapshot reference is stable.

Test plan

  • Open a fresh task (no prior deploys) and confirm <DeployControl /> renders without the React error overlay.
  • Run a deploy → verify the success row + history dropdown still work, and the deployments count updates as before.
  • Switch between tasks (one with deploys, one without) and confirm no render loop is triggered.

🤖 Generated with Claude Code

The `?? []` fallback in the `deployments` zustand selector allocated
a fresh array every render when the active task had no deployments,
making `Object.is` see a new snapshot each call and triggering
"getSnapshot should be cached" + "Maximum update depth exceeded".

Hoist a module-level `EMPTY_DEPLOYMENTS` constant and return it from
the selector so the snapshot is reference-stable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lefarcen

Copy link
Copy Markdown

Heads-up: #37 is now open and also touches src/components/deploy-control.tsx for the empty deployments selector fallback behind #32. This PR is the focused bugfix, while #37 includes that stabilization as part of a larger per-task history feature.

You and @wuwangzhang1216 may want to compare scope; the maintainer team will decide which path lands so neither effort gets wasted.

@lefarcen

Copy link
Copy Markdown

Adding one more coordination note: PR #25 is also open against this same DeployControl empty-deployments selector loop. Both PRs make the fallback reference stable in src/components/deploy-control.tsx, with #31/#32 carrying the user-facing error reports.

The maintainer team will choose which focused fix to land; noting the overlap so everyone has the full picture.

@lefarcen

Copy link
Copy Markdown

Heads-up: PR #41 is now also open against this same DeployControl selector loop. Both PRs touch src/components/deploy-control.tsx and use a shared empty deployments array to avoid the unstable deployments ?? [] fallback.

You and @jidechao may want to compare approaches; the maintainer team will decide which one lands. Sharing this so neither effort gets wasted.

@lefarcen

Copy link
Copy Markdown

Adding one more coordination note: PR #42 is now also open against this same DeployControl selector loop. It touches src/components/deploy-control.tsx and uses the same stable empty deployments fallback direction as the focused fixes here and in #41.

The maintainer team will choose which focused fix lands; noting the overlap so everyone has the latest picture.

@joeylee12629-star joeylee12629-star left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Cleanest of the four duplicates — readonly type + module-scope constant fixes the getSnapshot infinite loop without touching the selectActiveTask helper.

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

Labels

risk/medium Medium risk change size/XS Extra-small change (<20 lines) type/bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants