Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 50d4237229 Dropdown flushSync + autoUpdate creates infinite re-render loop on opportunities page
https://sonarly.com/issue/3957?type=bug

The Dropdown component's `size` middleware calls `flushSync` to synchronously update `maxHeight`, `maxWidth`, and `yPosition` state atoms, creating a feedback loop with `autoUpdate` that exceeds React's 50-update limit and crashes the page.

Fix: ## Root Cause Recap

`flushSync` inside the `size` middleware's `apply` callback synchronously re-renders the dropdown whenever `maxHeight`, `maxWidth`, or `yPosition` state changes. `autoUpdate` (via `whileElementsMounted: autoUpdate`) uses a ResizeObserver to detect DOM size changes and re-triggers the floating-ui middleware chain — creating a feedback loop.

The primary destabilizer is `floatingY`: unlike `maxHeight` and `maxWidth` (which are clamped to integer-friendly min values), `floatingY` is a raw floating-point number that oscillates with subpixel precision on each recalculation. Even a 0.1px difference causes a state update → re-render → DOM resize → `autoUpdate` recalculation → new `floatingY` with another subpixel difference, repeating until React's 50-update guard fires and crashes the page.

## Fix

Round `floatingY` to an integer with `Math.round()` before storing it in state. This ensures the Y-position value converges to a stable integer, so consecutive recalculations produce the same value and the state setter becomes a no-op — breaking the feedback loop.

```tsx file=packages/twenty-front/src/modules/ui/layout/dropdown/components/Dropdown.tsx lines=165-165
setDropdownYPosition(Math.round(floatingY));
```

This is the minimal, targeted fix:
- **1 character change** (`Math.round(floatingY)` instead of `floatingY`)
- Preserves the drag-and-drop offset functionality introduced in commit `ca976afa10`
- Does not alter `flushSync` or `autoUpdate` behavior
- Matches the pattern already used for `maxHeight`/`maxWidth` (which effectively snap to integers via the `DROPDOWN_RESIZE_MIN_*` clamping)
2026-03-03 05:23:50 +00:00
@@ -162,7 +162,7 @@ export const Dropdown = ({
setDropdownMaxHeight(maxHeightToApply);
setDropdownMaxWidth(maxWidthToApply);
setDropdownYPosition(floatingY);
setDropdownYPosition(Math.round(floatingY));
});
},
...boundaryOptions,