From e176ecc5931ad4d774db6789074e7fe514dea2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Wed, 21 Oct 2026 11:38:17 +0200 Subject: [PATCH 1/3] [Docs] Document gesture cancellation when a detectors view is reordered --- .../docs/core-components/gesture-detector.mdx | 76 +++++++++++++++++++ .../docs/guides/upgrading-to-3.mdx | 35 ++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx b/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx index 16ac8c3bf9..eff513938a 100644 --- a/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx +++ b/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx @@ -177,6 +177,82 @@ const styles = StyleSheet.create({ `}/> +#### Views reordered during a gesture + +When a re-render changes `GestureDetector`'s place in the view hierarchy (e.g., a drag-to-reorder list puts the held row at a new index), Fabric detaches the view and reattaches it, therefore the active gesture is cancelled. + +On Android, you can keep the gesture alive by wrapping the list in `InterceptingGestureDetector` and using `VirtualGestureDetector` for each row. The gesture is then attached through the list's detector, which stays in place. + +On iOS the system cancels the gesture of a reattached view regardless of the detector used. + + void }; + +function Row({ id, onGrab }: RowProps) { + const pan = usePanGesture({ + runOnJS: true, + onActivate: () => onGrab(id), + }); + + return ( + + + {id} + + + ); +} + +export default function App() { + const [rows, setRows] = useState(['A', 'B', 'C', 'D']); + + const onGrab = (id: string) => + setRows((current) => [id, ...current.filter((row) => row !== id)]); + + return ( + + + id} + renderItem={({ item }) => } + /> + + + ); +} + +const styles = StyleSheet.create({ + container: { flex: 1, padding: 16 }, + row: { + height: 80, + marginBottom: 12, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#001A72', + }, + text: { + color: 'white', + fontWeight: 'bold', + fontSize: 20, + }, +}); +`}/> + + ## Properties ### gesture diff --git a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx index 45cd592f9a..46f9e9bf3a 100644 --- a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx +++ b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx @@ -271,9 +271,9 @@ Full changes are as follows: | `blocksHandlers` | `block` | -## Migrating components relying on view hierarchy +## Migrating to virtual detectors -Certain components, such as `SVG`, depend on the view hierarchy to function correctly. In Gesture Handler 3, `GestureDetector` disrupts these hierarchies. To resolve this issue, two new detectors have been introduced: [`InterceptingGestureDetector`](/docs/core-components/gesture-detectors#interceptinggesturedetector) and [`VirtualGestureDetector`](/docs/core-components/gesture-detectors#virtualgesturedetector). +In Gesture Handler 3, `GestureDetector` is a host view. This has two consequences: it disrupts components that depend on the view hierarchy, such as `SVG`, and it is detached and reattached when its place in the hierarchy changes, which cancels an active gesture. To handle both cases, two new detectors have been introduced: [`InterceptingGestureDetector`](/docs/core-components/gesture-detectors#interceptinggesturedetector) and [`VirtualGestureDetector`](/docs/core-components/gesture-detectors#virtualgesturedetector). :::danger Detectors order `VirtualGestureDetector` has to be a descendant of `InterceptingGestureDetector`. @@ -308,6 +308,37 @@ code2={ `} /> +### Migrating views reordered during a gesture + +In Gesture Handler 2, a gesture on Android survived its view being reordered mid-gesture, for example a drag-to-reorder list putting the held row at a new index. To keep that behavior, use `InterceptingGestureDetector` and `VirtualGestureDetector`. See [Views reordered during a gesture](/docs/core-components/gesture-detectors#views-reordered-during-a-gesture) for details. + + ( + + + + )} +/> +`} +code2={ +` + + ( + + + + )} + /> + +`} +/> + ## Old components ### Buttons From 3885cf5a824da90af6b9dc8233c7213b5d340b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Wed, 21 Oct 2026 12:19:18 +0200 Subject: [PATCH 2/3] Update migration guide --- .../docs/guides/upgrading-to-3.mdx | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx index 46f9e9bf3a..5ae03bf5c0 100644 --- a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx +++ b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx @@ -317,24 +317,32 @@ label1={"RNGH 2"} label2={"RNGH 3"} code1={ ` - ( +function Row() { + const pan = Gesture.Pan(); + + return ( - + - )} -/> + ); +} + + } /> `} code2={ ` +function Row() { + const pan = usePanGesture(); + + return ( + + + + ); +} + - ( - - - - )} - /> + } /> `} /> From 31ca739d739e1b4161ead14334e4e95e44fc7367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Mon, 26 Oct 2026 16:20:24 +0100 Subject: [PATCH 3/3] Mention web --- .../docs/core-components/gesture-detector.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx b/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx index eff513938a..d5991fa398 100644 --- a/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx +++ b/packages/docs-gesture-handler/docs/core-components/gesture-detector.mdx @@ -179,11 +179,11 @@ const styles = StyleSheet.create({ #### Views reordered during a gesture -When a re-render changes `GestureDetector`'s place in the view hierarchy (e.g., a drag-to-reorder list puts the held row at a new index), Fabric detaches the view and reattaches it, therefore the active gesture is cancelled. +When a re-render changes `GestureDetector`'s place in the view hierarchy (e.g., a drag-to-reorder list puts the held row at a new index), the renderer may detach the view and reattach it, which cancels the active gesture. On Android, you can keep the gesture alive by wrapping the list in `InterceptingGestureDetector` and using `VirtualGestureDetector` for each row. The gesture is then attached through the list's detector, which stays in place. -On iOS the system cancels the gesture of a reattached view regardless of the detector used. +On iOS and web the system cancels the gesture of a reattached view regardless of the detector used.