Skip to content

Commit bc210f6

Browse files
committed
fix(canvas): select from useWorkflowRegistry instead of subscribing whole
check-zustand-v5-selectors matched /use[A-Z]\w*Store\(/, and exactly one Zustand store in the repo is not named with a Store suffix — useWorkflowRegistry. So the store behind the canvas went unchecked, and two bare whole-store subscriptions had accumulated in the action bar, re-rendering it on every registry mutation (clipboard, hydration, pendingSelection, activeWorkflowId). Every other call site in the repo already uses a selector. Widens the pattern to (?:Store|Registry) and fixes both call sites. The widened gate reports these two and nothing else, so there is no cleanup tail.
1 parent 214a19d commit bc210f6

2 files changed

Lines changed: 8 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/action-bar/action-bar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ export const ActionBar = memo(
205205
collaborativeBatchToggleBlockEnabled,
206206
collaborativeBatchToggleLocked,
207207
} = useCollaborativeWorkflow()
208-
const { setPendingSelection } = useWorkflowRegistry()
208+
const setPendingSelection = useWorkflowRegistry((state) => state.setPendingSelection)
209209
const { handleCancelExecution, handleRunFromBlock } = useWorkflowExecution()
210210
const handleDuplicateBlock = useCallback(() => {
211211
const { copyBlocks, preparePasteData } = useWorkflowRegistry.getState()
@@ -249,7 +249,7 @@ export const ActionBar = memo(
249249
})
250250
)
251251

252-
const { activeWorkflowId } = useWorkflowRegistry()
252+
const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
253253
const snapshot = useLastExecutionSnapshot(activeWorkflowId)
254254
const userPermissions = useUserPermissionsContext()
255255
const edges = useWorkflowStore((state) => state.edges)

scripts/check-zustand-v5-selectors.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ const APP_DIR = path.join(ROOT, 'apps/sim')
88
const SKIP_DIRS = new Set(['node_modules', '.next', '.turbo', 'coverage', 'dist', 'build'])
99

1010
const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])
11-
const STORE_HOOK_CALL_PATTERN = /\buse[A-Z][A-Za-z0-9_]*Store\s*\(/g
11+
/**
12+
* Zustand store hooks are named `use<Name>Store` by convention, with one
13+
* exception: `useWorkflowRegistry`. Matching only the `Store` suffix left that
14+
* store — one of the hottest in the canvas — entirely unchecked.
15+
*/
16+
const STORE_HOOK_CALL_PATTERN = /\buse[A-Z][A-Za-z0-9_]*(?:Store|Registry)\s*\(/g
1217
const SAFE_ANNOTATION = 'zustand-v5-safe:'
1318
const UNSAFE_SELECTOR_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [
1419
{

0 commit comments

Comments
 (0)