Description
When the data of a Sortable.Grid changes in a way that is not a reorder — appending a new item (add), or replacing an item in place while keeping the same keyExtractor key — the grid's internal layout sometimes goes stale:
- an empty gap is left where a row should be, or
- the replaced item renders blank / disappears.
The grid never re-measures the affected row on its own. The bug fixes itself the instant a drag gesture starts — beginning a drag forces a re-measure/relayout and the gap or missing item immediately snaps back into place.
So it appears that structural data changes that don't change item order don't reliably trigger a re-measure of the affected row, and the drag handler is what forces it.
This looks closely related to the (closed) #286 — "New items are sometimes placed in the wrong position" / "the last item added is invisible".
Expected behavior
After adding or replacing an item, the grid should lay out the new/changed row correctly without requiring a drag gesture to trigger a relayout.
Notes / workaround
Keeping a stable keyExtractor key across reorders is intentional in our app (so a slot keeps its drag identity when its content is replaced). Our current workaround is to bump a React key on the Sortable.Grid itself — forcing a full remount — only when an add/replace happens (detected via an order-independent signature of key → itemId), and not on reorder. A remount produces a correct layout, which further suggests the issue is a missed internal re-measure rather than bad data.
Steps to reproduce
- Render a single-column
Sortable.Grid with a keyExtractor returning a stable per-item id.
- From a button (outside the grid), append a new item to
data — or replace an existing item with a new one while returning the same keyExtractor key for that slot.
- Observe (intermittently) an empty gap where the new/changed row should be, or the replaced row rendered blank.
- Start dragging any row — the layout immediately corrects itself.
Code snippet, Snack or GitHub repository link
We have not yet isolated this in the example app (the same difficulty noted in #286 — it reproduces in our app but is intermittent). The grid is used roughly like this:
const keyExtractor = useCallback(
(item: Item) => item.uid, // stable per-slot id; survives replace
[]
);
<Sortable.Grid
columns={1}
data={items}
dimensionsAnimationType="layout"
keyExtractor={keyExtractor}
scrollableRef={scrollRef}
rowGap={0}
columnGap={0}
onDragEnd={({ data }) => setItems(data)}
renderItem={({ item }) => (
<Animated.View
layout={LinearTransition.duration(220)}
exiting={FadeOut.duration(160)}
>
<Row item={item} />
</Animated.View>
)}
/>
// elsewhere:
// add: setItems(prev => [...prev, newItem])
// replace: setItems(prev => prev.map(i => i.uid === target.uid ? { ...replacement, uid: i.uid } : i))
I'm happy to put together a standalone repro if it would help — please let me know.
React Native Sortables version
1.9.4
Reanimated version
4.3.1
React Native Gesture Handler version
2.31.2
React Native version
0.85.3
Platforms
iOS (confirmed via screen recording). Suspected on Android as well — #286 reported the "invisible last item" specifically on Android.
Additional information
- React: 19.2.3
- Expo SDK: 56
- Architecture: Fabric (New Architecture)
- Workflow: Expo Dev Client
dimensionsAnimationType="layout", columns={1}, rowGap={0}, columnGap={0}, rows wrapped in an Animated.View with Reanimated LinearTransition layout + FadeOut exiting animations.
Description
When the
dataof aSortable.Gridchanges in a way that is not a reorder — appending a new item (add), or replacing an item in place while keeping the samekeyExtractorkey — the grid's internal layout sometimes goes stale:The grid never re-measures the affected row on its own. The bug fixes itself the instant a drag gesture starts — beginning a drag forces a re-measure/relayout and the gap or missing item immediately snaps back into place.
So it appears that structural
datachanges that don't change item order don't reliably trigger a re-measure of the affected row, and the drag handler is what forces it.This looks closely related to the (closed) #286 — "New items are sometimes placed in the wrong position" / "the last item added is invisible".
Expected behavior
After adding or replacing an item, the grid should lay out the new/changed row correctly without requiring a drag gesture to trigger a relayout.
Notes / workaround
Keeping a stable
keyExtractorkey across reorders is intentional in our app (so a slot keeps its drag identity when its content is replaced). Our current workaround is to bump a Reactkeyon theSortable.Griditself — forcing a full remount — only when an add/replace happens (detected via an order-independent signature ofkey → itemId), and not on reorder. A remount produces a correct layout, which further suggests the issue is a missed internal re-measure rather than bad data.Steps to reproduce
Sortable.Gridwith akeyExtractorreturning a stable per-item id.data— or replace an existing item with a new one while returning the samekeyExtractorkey for that slot.Code snippet, Snack or GitHub repository link
We have not yet isolated this in the example app (the same difficulty noted in #286 — it reproduces in our app but is intermittent). The grid is used roughly like this:
I'm happy to put together a standalone repro if it would help — please let me know.
React Native Sortables version
1.9.4
Reanimated version
4.3.1
React Native Gesture Handler version
2.31.2
React Native version
0.85.3
Platforms
iOS (confirmed via screen recording). Suspected on Android as well — #286 reported the "invisible last item" specifically on Android.
Additional information
dimensionsAnimationType="layout",columns={1},rowGap={0},columnGap={0}, rows wrapped in anAnimated.Viewwith ReanimatedLinearTransitionlayout +FadeOutexiting animations.