- Shipped
- August 22, 2026 at 7:34 PM UTC
- Author
- kamo
- Commit
- 935a18b
Dragging a pane sometimes threw React #185 and left the page scrolling to the bottom forever, undoing every attempt to scroll back up. One cause, two symptoms. `onDragOver` reorders the real array to draw the "insert between" preview; SortableContext re-measures every droppable whenever its items change mid-drag; fresh rects re-run collision detection and can name a different pane as `over`; a changed `over` fires onDragOver again — with no pointer input at all. That settled while every pane was the same size, which is what it was when the live preview landed. Panes then became 1-4 columns wide and 1-4 half rows tall, so a swap repacks the whole grid and the pane under a still synchronous React burst until the nested-update limit trips, which is the #185 reported from dnd-kit's own useRects. The runaway scroll is that crash's wreckage. dnd-kit's auto-scroller starts a 5ms scrollBy interval from inside an effect, and useInterval in @dnd-kit/utilities has no unmount cleanup — the interval is cleared only if that effect runs again, which throwing mid-drag prevents. Nothing outside dnd-kit can clear it, so the only cure is not to throw. Gated on two independent guards: one reorder per animation frame, which refuses the echo because the cascade is synchronous; and travel since the last reorder, because an echo carries the delta of the reorder that caused it however late it arrives. Both are pure and covered, including the property that matters — a 500-iteration cascade over a stationary pointer yields exactly one reorder.