diff --git a/docs-site/docs/api/components/sortable-item.mdx b/docs-site/docs/api/components/sortable-item.mdx index 9d415e5..dd155eb 100644 --- a/docs-site/docs/api/components/sortable-item.mdx +++ b/docs-site/docs/api/components/sortable-item.mdx @@ -102,7 +102,7 @@ Returns: `itemKey`, `index`, `isActive` (SharedValue), `activeItemId` (SharedVal - Shift values come from `shiftsRef` SharedValue (keyed by item key) - Visibility controlled by `hoverReadySV` + `draggedIdSV` — hidden when being dragged - Measures itself on layout and stores in `itemMeasurements` Map -- Calls `onItemSnapEnd` when snap-back completes (triggers reorder finalization) +- Calls `onItemSnapEndRef.current` when snap-back completes (triggers reorder finalization) - Respects reduced motion via `useReducedMotion()` ## Related diff --git a/docs-site/versioned_docs/version-1.x/api/components/sortable-item.mdx b/docs-site/versioned_docs/version-1.x/api/components/sortable-item.mdx index 9d415e5..dd155eb 100644 --- a/docs-site/versioned_docs/version-1.x/api/components/sortable-item.mdx +++ b/docs-site/versioned_docs/version-1.x/api/components/sortable-item.mdx @@ -102,7 +102,7 @@ Returns: `itemKey`, `index`, `isActive` (SharedValue), `activeItemId` (SharedVal - Shift values come from `shiftsRef` SharedValue (keyed by item key) - Visibility controlled by `hoverReadySV` + `draggedIdSV` — hidden when being dragged - Measures itself on layout and stores in `itemMeasurements` Map -- Calls `onItemSnapEnd` when snap-back completes (triggers reorder finalization) +- Calls `onItemSnapEndRef.current` when snap-back completes (triggers reorder finalization) - Respects reduced motion via `useReducedMotion()` ## Related diff --git a/src/SortableContainer.tsx b/src/SortableContainer.tsx index 9f1d0ae..8dd4008 100644 --- a/src/SortableContainer.tsx +++ b/src/SortableContainer.tsx @@ -214,7 +214,7 @@ export const SortableContainer = ({ // calls the latest version, even if it has a stale _internal reference // (e.g., after MATCH path skips FlatList re-render). useLayoutEffect(() => { - sortable._internal.onItemSnapEnd = finalizeDrag; + sortable._internal.onItemSnapEndRef.current = finalizeDrag; }, [sortable._internal, finalizeDrag]); // ── Auto-scroll ───────────────────────────────────────────────────── diff --git a/src/SortableItem.tsx b/src/SortableItem.tsx index c5504c8..54cf530 100644 --- a/src/SortableItem.tsx +++ b/src/SortableItem.tsx @@ -126,7 +126,7 @@ const SortableItemInner = ({ rawData, originalIndexes, scrollPosition, - onItemSnapEnd, + onItemSnapEndRef, fixedKeys, } = sortable._internal; @@ -221,7 +221,7 @@ const SortableItemInner = ({ draxViewProps.onDragDrop?.(event); }} onSnapEnd={(snapData) => { - onItemSnapEnd?.(); + onItemSnapEndRef.current?.(); draxViewProps.onSnapEnd?.(snapData); }} onMeasure={(measurements) => { diff --git a/src/hooks/useSortableList.ts b/src/hooks/useSortableList.ts index 1ff54d0..129bec6 100644 --- a/src/hooks/useSortableList.ts +++ b/src/hooks/useSortableList.ts @@ -121,6 +121,13 @@ export const useSortableList = ( // ── Drag tracking (refs, no re-render) ──────────────────────────── const draggedDisplayIndexRef = useRef(undefined); const dragStartIndexRef = useRef(undefined); + /** + * Holds the `finalizeDrag` callback registered by `SortableContainer`. + * A ref (not a plain property) so `SortableItem` reads the latest value at + * call time — `_internal` is rebuilt every render, so a value stored on it + * directly is always `undefined` for consumers that destructure at render. + */ + const onItemSnapEndRef = useRef<(() => void) | undefined>(undefined); /** * Pending reorder during drag. Tracks the desired display order * as indices into rawData. Updated by moveDraggedItem (ref, not state). @@ -1023,7 +1030,7 @@ export const useSortableList = ( getMeasurementByOriginalIndex, dropTargetPositionSV, dropTargetVisibleSV, - onItemSnapEnd: undefined as (() => void) | undefined, + onItemSnapEndRef, draggedDisplayIndexRef, dragStartIndexRef, shiftsRef, diff --git a/src/types.ts b/src/types.ts index f393ffc..2e8d274 100644 --- a/src/types.ts +++ b/src/types.ts @@ -812,7 +812,7 @@ export interface SortableListInternal { /** Called by SortableItem's onSnapEnd to finalize the drag. * Stored as a ref so the latest finalizeDrag is always called, * even if SortableItem has a stale _internal reference. */ - onItemSnapEnd?: () => void; + onItemSnapEndRef: RefObject<(() => void) | undefined>; /** Current display index of the dragged item (updated during live reorder) */ draggedDisplayIndexRef: RefObject; /** Original display index where the drag started */