Skip to content

Commit c80aee4

Browse files
authored
[Web] Change shouldBeCancelledByOther to respect blocksExternalGesture (#3429)
## Description While checking possibilities of blocking `FlatList` with gestures using `blocksExternalHandler`, I've found out that even though `FlatList` doesn't scroll, `Tap` fails. Turns out that `shouldBeCancelledByOther` method doesn't respect blocking relation. I've changed the approach and when checking `isActive` now I use `handler.active` instead of comparing to `STATE.ACTIVE`, as the state can be set to `4`, but handler may be awaiting. ## Test plan <details> <summary>Tested on the following code:</summary> ```jsx import React from 'react'; import { StyleSheet, Text, View, FlatList, ScrollView } from 'react-native'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; const data = [ { id: '1', title: 'Item 1' }, { id: '2', title: 'Item 2' }, { id: '3', title: 'Item 3' }, { id: '4', title: 'Item 4' }, { id: '5', title: 'Item 5' }, { id: '6', title: 'Item 6' }, { id: '7', title: 'Item 7' }, { id: '8', title: 'Item 8' }, { id: '9', title: 'Item 9' }, { id: '10', title: 'Item 10' }, { id: '11', title: 'Item 11' }, { id: '12', title: 'Item 12' }, { id: '13', title: 'Item 13' }, { id: '14', title: 'Item 14' }, { id: '15', title: 'Item 15' }, { id: '16', title: 'Item 16' }, ]; const SimpleFlatList = () => { const native = Gesture.Native(); const renderItem = ({ item }) => { const g = Gesture.Tap() .onEnd(() => { console.log(`Tapped ${item.id}`); }) .onFinalize((e, s) => console.log(e, s)) .maxDistance(1000) .maxDuration(1000) .shouldCancelWhenOutside(false) .blocksExternalGesture(native); return ( <GestureDetector gesture={g}> <View style={styles.itemContainer}> <Text style={styles.itemText}>{item.title}</Text> </View> </GestureDetector> ); }; const CustomScrollComponent = React.forwardRef((props, ref) => { return ( <GestureDetector gesture={native}> <ScrollView {...props} ref={ref} /> </GestureDetector> ); }); return ( <FlatList data={data} renderItem={renderItem} renderScrollComponent={(props) => <CustomScrollComponent {...props} />} keyExtractor={(item) => item.id} /> ); }; export default function EmptyExample() { return ( <View style={styles.container}> <SimpleFlatList /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, itemContainer: { padding: 10, marginVertical: 8, backgroundColor: '#f9c2ff', }, itemText: { fontSize: 18, }, }); ``` </details>
1 parent 249bff2 commit c80aee4

File tree

2 files changed

+1
-3
lines changed

2 files changed

+1
-3
lines changed

src/web/tools/GestureHandlerOrchestrator.ts

-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,6 @@ export default class GestureHandlerOrchestrator {
307307
}
308308

309309
if (handler.awaiting || handler.state === State.ACTIVE) {
310-
// For now it always returns false
311310
return handler.shouldBeCancelledByOther(otherHandler);
312311
}
313312

src/web/tools/InteractionManager.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type IGestureHandler from '../handlers/IGestureHandler';
2-
import { State } from '../../State';
32
import { Config, Handler } from '../interfaces';
43

54
export default class InteractionManager {
@@ -108,7 +107,7 @@ export default class InteractionManager {
108107
// We check constructor name instead of using `instanceof` in order do avoid circular dependencies
109108
const isNativeHandler =
110109
otherHandler.constructor.name === 'NativeViewGestureHandler';
111-
const isActive = otherHandler.state === State.ACTIVE;
110+
const isActive = otherHandler.active;
112111
const isButton = otherHandler.isButton?.() === true;
113112

114113
return isNativeHandler && isActive && !isButton;

0 commit comments

Comments
 (0)