Skip to content

v0.6.73: zustand v5 migration fix #4540

Merged
icecrasher321 merged 3 commits intomainfrom
staging
May 9, 2026
Merged

v0.6.73: zustand v5 migration fix #4540
icecrasher321 merged 3 commits intomainfrom
staging

Conversation

@icecrasher321
Copy link
Copy Markdown
Collaborator

@icecrasher321 icecrasher321 commented May 9, 2026

fix(zustand): v5 selector stability issues (#4539)
fix(script): biome format wrap (#4541)
improvement(deps): remove unused remark deps (#4542)

* fix(zustand): v5 selector stability issues

* address comments
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment May 9, 2026 11:38pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 9, 2026

PR Summary

Medium Risk
Touches multiple Zustand store selector call sites and adds a CI-enforced audit script, so regressions would show up as UI re-render bugs or new CI failures. Also reformats/rewrites generated schema outputs, which could cause noisy diffs or unexpected downstream assumptions about generated module structure.

Overview
Fixes several Zustand v5 migration hazards by switching store subscriptions to stable selectors (e.g., using useShallow, useStoreWithEqualityFn, and stable empty fallbacks) instead of subscribing to whole stores or returning newly-allocated objects/arrays.

Adds a check:zustand-v5 script plus a CI step to fail PRs that introduce unsafe store selectors, and refactors contract/codegen scripts to run generated outputs through a shared Biome formatter (including updating generated tool-schemas-v1.ts object keys to bracket notation for consistency).

Reviewed by Cursor Bugbot for commit 13666b1. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 9, 2026

Greptile Summary

This PR fixes Zustand v5 selector stability issues across multiple components and hooks, replacing whole-store subscriptions and useCallback-only selectors with useShallow, single-field primitive selectors, stable empty-object constants, and useStoreWithEqualityFn + deep equality for derived collections. It also introduces a new CI audit script (check-zustand-v5-selectors.ts) that statically detects unsafe selector patterns, and extracts a shared formatGeneratedSource utility used by the contract-sync scripts.

  • App-layer fixes: action-bar.tsx, use-block-properties.ts, workflow-search-replace.tsx, tag-dropdown.tsx, credential-selector.tsx, file-upload.tsx, connection-blocks.tsx, use-reactive-conditions.ts, and use-folder-expand.ts are all updated to emit stable selector return values so Zustand v5's Object.is equality check no longer triggers spurious re-renders.
  • New audit script: check-zustand-v5-selectors.ts scans apps/sim for unsafe patterns (inline object/array literals, .map/.filter in selectors, ??/|| with unstable fallbacks, unguarded full-store subscriptions) and runs in CI via a new check:zustand-v5 step.
  • Script refactor: formatGeneratedSource is extracted and applied to contract-sync scripts, but sync-tool-catalog.ts only applies it to its main output, not to the runtime schema module output.

Confidence Score: 3/5

Safe to merge for all React component changes; the script inconsistency in sync-tool-catalog.ts will break the mship-tools:check CI step on the next contract regeneration.

The component-level Zustand fixes are correct and well-structured. In sync-tool-catalog.ts, formatGeneratedSource is applied to the main catalog output but not to runtimeSchemaRendered, while tool-schemas-v1.ts was committed with biome-formatted single-quote bracket notation. The generator emits double-quote bracket notation via JSON.stringify, so the check-mode string comparison will mismatch on the next run.

scripts/sync-tool-catalog.ts needs formatGeneratedSource applied to runtimeSchemaRendered, matching the pattern already used in sync-mothership-stream-contract.ts.

Important Files Changed

Filename Overview
scripts/sync-tool-catalog.ts Applies formatGeneratedSource to the main catalog output but not to runtimeSchemaRendered, while the committed tool-schemas-v1.ts was updated to biome-formatted style — this will break the mship-tools:check CI step on the next run.
scripts/check-zustand-v5-selectors.ts New AST-light audit script that walks the apps/sim source tree, finds all useXxxStore() calls, and enforces stable selector patterns for Zustand v5 compatibility.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx Replaces whole-store destructuring and bare useCallback selectors with useShallow-wrapped selectors and single-field primitive selectors.
apps/sim/app/workspace/[workspaceId]/w/components/sidebar/hooks/use-folder-expand.ts Extracts stable action references at module scope via useFolderStore.getState(), eliminating unnecessary store subscriptions for functions that never change.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown.tsx Replaces getVariablesByWorkflowId derived call with useStoreWithEqualityFn + isEqual deep equality, correctly preventing infinite re-renders from a freshly allocated filtered array.
apps/sim/stores/workflows/subblock/store.ts Adds EMPTY_BLOCK_SUBBLOCK_VALUES stable constant to prevent fresh object allocation on every selector call for a single block's sub-block values.
apps/sim/lib/copilot/generated/tool-schemas-v1.ts All property keys reformatted from shorthand to computed bracket notation by biome. Purely cosmetic; no logic changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Component renders] --> B{Selector type}
    B -->|Primitive value| C["useStore(s => s.field)"]
    B -->|Object or multiple fields| D["useStore(useShallow(s => object))"]
    B -->|Derived array or collection| E["useStoreWithEqualityFn(store, selector, isEqual)"]
    B -->|Store action only| F["getState at module scope"]
    C --> G["Object.is equality"]
    D --> H["shallow equality"]
    E --> I["deep equality"]
    F --> J["No subscription"]
    G --> K[Re-render only on value change]
    H --> K
    I --> K
    J --> L[Zero re-renders for actions]
Loading

Reviews (1): Last reviewed commit: "fix(zustand): v5 selector stability issu..." | Re-trigger Greptile

Comment thread scripts/sync-tool-catalog.ts Outdated
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 13666b1. Configure here.

Comment thread scripts/sync-tool-catalog.ts
@icecrasher321 icecrasher321 merged commit dcaf3e9 into main May 9, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant