Repository navigation
Commit c5db1fc
authored
[Web] Drop a handler from the orchestrator when it gets disabled mid-gesture (#4504)
## Description
Disabling a `Touchable`/`Pressable` while a press was in progress killed
every other button on the page: nothing pressed after that would begin.
When a handler is disabled mid-gesture, `updateGestureConfig` cancels it
and `moveToState` immediately resets the disabled handler back to
`UNDETERMINED`. The orchestrator's finished-handler cleanup runs later
in a microtask and only drops handlers whose state is finished, so it
skipped this one and left it recorded. Every later button consulted that
stale entry in `shouldBeginWithRecordedHandlers` and cancelled itself.
`updateGestureConfig` now resets the handler and removes it from the
orchestrator itself after the `cancel`/`fail`. A handler that never
began still skips the cancel, as before, and is just reset and
unrecorded.
The web button also resets its press visuals instantly instead of
running the press-out transition when the cancel comes from the disable
itself: no pointer lifted, and a disable usually restyles the button in
the same frame, so the fade showed as a brief flash.
## Test plan
Added a test in `GestureHandler.test.ts` that fails without the fix.
Manually: a `Touchable` that disables itself shortly after `onPressIn`,
e.g. a 700 ms timeout, held past that point, next to a second
`Touchable` that re-enables it.
- `onPressOut` fires when the button gets disabled and `onPress` does
not fire on release
- the second button still works afterwards
- after re-enabling, the first button works again
- the button snaps to its resting look on disable, with no flash
<details>
<summary>Tested on the following code:</summary>
```tsx
import React, { useCallback, useRef, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Touchable } from 'react-native-gesture-handler';
// A button that gets disabled while a press is in progress.
// Press and hold the blue box. After `DISABLE_AFTER_MS` it disables itself.
// Expected: onPressOut fires at that moment, onPress never fires on release,
// and the press animation resets instead of staying stuck (macOS especially).
const DISABLE_AFTER_MS = 700;
export default function EmptyExample() {
const [disabled, setDisabled] = useState(false);
const [log, setLog] = useState<string[]>([]);
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
const push = useCallback((entry: string) => {
console.log(`RNGH-mid-press: ${entry}`);
setLog((l) => [...l.slice(-7), entry]);
}, []);
const onPressIn = useCallback(() => {
push('onPressIn');
timer.current = setTimeout(() => {
push(`disabled after ${DISABLE_AFTER_MS}ms`);
setDisabled(true);
}, DISABLE_AFTER_MS);
}, [push]);
const onPressOut = useCallback(() => {
push('onPressOut');
if (timer.current) {
clearTimeout(timer.current);
timer.current = null;
}
}, [push]);
const onPress = useCallback(() => push('onPress'), [push]);
const reset = useCallback(() => {
setDisabled(false);
setLog([]);
}, []);
return (
<View style={styles.container}>
<Text>
Hold the box for longer than {DISABLE_AFTER_MS}ms. It disables itself
mid-press.
</Text>
<Touchable
disabled={disabled}
onPressIn={onPressIn}
onPressOut={onPressOut}
onPress={onPress}
activeOpacity={0.4}
style={[styles.box, disabled ? styles.boxDisabled : styles.boxEnabled]}>
<Text style={styles.boxText}>{disabled ? 'disabled' : 'hold me'}</Text>
</Touchable>
<Touchable onPress={reset} style={styles.reset}>
<Text style={styles.boxText}>re-enable and clear log</Text>
</Touchable>
{log.map((entry, i) => (
<Text key={i} style={styles.log}>
{entry}
</Text>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
gap: 12,
},
box: {
height: 100,
borderRadius: 8,
justifyContent: 'center',
alignItems: 'center',
},
boxEnabled: {
backgroundColor: '#5b7bd5',
},
boxDisabled: {
backgroundColor: '#9a9a9a',
},
boxText: {
color: 'white',
fontWeight: '600',
},
reset: {
height: 44,
borderRadius: 8,
backgroundColor: '#3a3a3a',
justifyContent: 'center',
alignItems: 'center',
},
log: {
fontVariant: ['tabular-nums'],
},
});
```
</details>1 parent eabe157 commit c5db1fc
4 files changed
Lines changed: 62 additions & 12 deletions
File tree
- packages/react-native-gesture-handler/src
- components
- web
- handlers
- __tests__
- tools
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
558 | 558 | | |
559 | 559 | | |
560 | 560 | | |
561 | | - | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
562 | 567 | | |
563 | 568 | | |
564 | 569 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
861 | 861 | | |
862 | 862 | | |
863 | 863 | | |
864 | | - | |
865 | | - | |
866 | | - | |
867 | | - | |
868 | | - | |
869 | | - | |
870 | | - | |
871 | | - | |
872 | | - | |
873 | | - | |
874 | | - | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
875 | 877 | | |
876 | 878 | | |
877 | 879 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| 5 | + | |
4 | 6 | | |
5 | 7 | | |
6 | 8 | | |
| |||
19 | 21 | | |
20 | 22 | | |
21 | 23 | | |
| 24 | + | |
22 | 25 | | |
23 | 26 | | |
24 | 27 | | |
| |||
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| 46 | + | |
43 | 47 | | |
44 | 48 | | |
45 | 49 | | |
| |||
74 | 78 | | |
75 | 79 | | |
76 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
35 | 40 | | |
36 | 41 | | |
37 | 42 | | |
| |||
0 commit comments