Skip to content

Commit a1a6da6

Browse files
authored
fix: #95 Re-render on iOS after reordering (#97)
This fixes a regression from #85 which introduced badly-rendered lists in iOS on subsequent drags. #85, funny enough, was trying to fix #76. The core cause of this was that `inReorderingRef` was inconsistent between renders right after reordering, triggered by `reset()`. We now update the ref prior to the reset. Issue would only reproduce on device, and only in more complicated apps than `/example` (I suspect because of re-rendering speeds). Also figured out we don't need to change keys on the items as long as we made this change. All in all, seems to work better. Tested on iOS device by integrating into a more complicated app, and on Android simulator.
1 parent 2fb0c1f commit a1a6da6

File tree

1 file changed

+5
-15
lines changed

1 file changed

+5
-15
lines changed

src/index.tsx

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ function DragListImpl<T>(
128128
);
129129
const reorderRef = useRef(props.onReordered);
130130
reorderRef.current = useMemo(() => props.onReordered, [props.onReordered]);
131+
const keyExtractorRef = useRef(keyExtractor);
132+
keyExtractorRef.current = useMemo(() => keyExtractor, [keyExtractor]);
131133

132134
// #76 When we finalize a reordering (i.e. when our parent gets `onReordered`), we need to
133135
// insulate ourselves from the parent changing the data we render without us controlling the
@@ -160,20 +162,6 @@ function DragListImpl<T>(
160162
[pan]
161163
);
162164

163-
// #76 - Add indirection to keyExtractor to change keys during reordering. Because native
164-
// implementations can/do recycle views at times, you need to deliberately rekey things during
165-
// reordering so the native implementation respects your new positions/styles/settings.
166-
const keyExtractorRef = useRef(keyExtractor);
167-
keyExtractorRef.current = useMemo(() => {
168-
return (item: T, index: number) => {
169-
const key = keyExtractor(item, index);
170-
if (isReorderingRef.current) {
171-
return key + "_reordering";
172-
}
173-
return key;
174-
};
175-
}, [keyExtractor]);
176-
177165
const shouldCapturePan = useCallback(() => {
178166
return !!activeDataRef.current && !isReorderingRef.current;
179167
}, []);
@@ -341,8 +329,10 @@ function DragListImpl<T>(
341329

342330
await reorderRef.current?.(activeIndex, panIndex.current);
343331
} finally {
344-
reset(); // Guarantee resetting by putting this in finally
332+
// This needs to come before reset(), which causes a re-render that depends on
333+
// isReorderingRef.current reflecting the fact we're not reordering anymore.
345334
isReorderingRef.current = false;
335+
reset(); // Guarantee resetting by putting this in finally
346336
}
347337
} else {
348338
// #76 - Only reset here if we're not going to reorder the list. If we are instead

0 commit comments

Comments
 (0)