Skip to content

Commit 45af39e

Browse files
latekvoj-piasecki
authored andcommitted
Fix Pressable onPress callback not working (#3597)
## Description Rendering `Pressable` during an active press resulted in `onPress` never being called. This PR moves `StateMachine` dependencies, such that it is not reset when `handlePressIn` or `handlePressOut` change. Fixes #3593 ## Test plan - Use the repro provided within #3593 - See how `onPress` is called correctly
1 parent fa6a818 commit 45af39e

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

packages/react-native-gesture-handler/src/components/Pressable/Pressable.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, {
22
useCallback,
3+
useEffect,
34
useLayoutEffect,
45
useMemo,
56
useRef,
@@ -35,10 +36,8 @@ import {
3536
RelationPropName,
3637
RelationPropType,
3738
} from '../utils';
38-
import {
39-
getConfiguredStateMachine,
40-
StateMachineEvent,
41-
} from './stateDefinitions';
39+
import { getStatesConfig, StateMachineEvent } from './stateDefinitions';
40+
import { PressableStateMachine } from './StateMachine';
4241

4342
const DEFAULT_LONG_PRESS_DURATION = 500;
4443
const IS_TEST_ENV = isTestEnv();
@@ -222,10 +221,12 @@ const Pressable = (props: PressableProps) => {
222221
[handleFinalize, innerHandlePressIn, onPress, onPressOut]
223222
);
224223

225-
const stateMachine = useMemo(
226-
() => getConfiguredStateMachine(handlePressIn, handlePressOut),
227-
[handlePressIn, handlePressOut]
228-
);
224+
const stateMachine = useMemo(() => new PressableStateMachine(), []);
225+
226+
useEffect(() => {
227+
const configuration = getStatesConfig(handlePressIn, handlePressOut);
228+
stateMachine.setStates(configuration);
229+
}, [handlePressIn, handlePressOut, stateMachine]);
229230

230231
const hoverInTimeout = useRef<number | null>(null);
231232
const hoverOutTimeout = useRef<number | null>(null);

packages/react-native-gesture-handler/src/components/Pressable/StateMachine.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
11
import { PressableEvent } from './PressableProps';
22

3-
interface StateDefinition {
3+
export interface StateDefinition {
44
eventName: string;
55
callback?: (event: PressableEvent) => void;
66
}
77

88
class PressableStateMachine {
9-
private states: StateDefinition[];
9+
private states: StateDefinition[] | null;
1010
private currentStepIndex: number;
1111
private eventPayload: PressableEvent | null;
1212

13-
constructor(steps: StateDefinition[]) {
14-
this.states = steps;
13+
constructor() {
14+
this.states = null;
1515
this.currentStepIndex = 0;
1616
this.eventPayload = null;
1717
}
1818

19+
public setStates(states: StateDefinition[]) {
20+
this.states = states;
21+
}
22+
1923
public reset() {
2024
this.currentStepIndex = 0;
2125
this.eventPayload = null;
2226
}
2327

2428
public handleEvent(eventName: string, eventPayload?: PressableEvent) {
29+
if (!this.states) {
30+
return;
31+
}
32+
2533
const step = this.states[this.currentStepIndex];
2634
this.eventPayload = eventPayload || this.eventPayload;
2735

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Platform } from 'react-native';
22
import { PressableEvent } from './PressableProps';
3-
import { PressableStateMachine } from './StateMachine';
3+
import { StateDefinition } from './StateMachine';
44

55
export enum StateMachineEvent {
66
NATIVE_BEGIN = 'nativeBegin',
@@ -9,11 +9,11 @@ export enum StateMachineEvent {
99
LONG_PRESS_TOUCHES_DOWN = 'longPressTouchesDown',
1010
}
1111

12-
function getAndroidStateMachine(
12+
function getAndroidStatesConfig(
1313
handlePressIn: (event: PressableEvent) => void,
1414
handlePressOut: (event: PressableEvent) => void
1515
) {
16-
return new PressableStateMachine([
16+
return [
1717
{
1818
eventName: StateMachineEvent.NATIVE_BEGIN,
1919
},
@@ -25,14 +25,14 @@ function getAndroidStateMachine(
2525
eventName: StateMachineEvent.FINALIZE,
2626
callback: handlePressOut,
2727
},
28-
]);
28+
];
2929
}
3030

31-
function getIosStateMachine(
31+
function getIosStatesConfig(
3232
handlePressIn: (event: PressableEvent) => void,
3333
handlePressOut: (event: PressableEvent) => void
3434
) {
35-
return new PressableStateMachine([
35+
return [
3636
{
3737
eventName: StateMachineEvent.LONG_PRESS_TOUCHES_DOWN,
3838
},
@@ -44,14 +44,14 @@ function getIosStateMachine(
4444
eventName: StateMachineEvent.FINALIZE,
4545
callback: handlePressOut,
4646
},
47-
]);
47+
];
4848
}
4949

50-
function getWebStateMachine(
50+
function getWebStatesConfig(
5151
handlePressIn: (event: PressableEvent) => void,
5252
handlePressOut: (event: PressableEvent) => void
5353
) {
54-
return new PressableStateMachine([
54+
return [
5555
{
5656
eventName: StateMachineEvent.NATIVE_BEGIN,
5757
},
@@ -66,14 +66,14 @@ function getWebStateMachine(
6666
eventName: StateMachineEvent.FINALIZE,
6767
callback: handlePressOut,
6868
},
69-
]);
69+
];
7070
}
7171

72-
function getMacosStateMachine(
72+
function getMacosStatesConfig(
7373
handlePressIn: (event: PressableEvent) => void,
7474
handlePressOut: (event: PressableEvent) => void
7575
) {
76-
return new PressableStateMachine([
76+
return [
7777
{
7878
eventName: StateMachineEvent.LONG_PRESS_TOUCHES_DOWN,
7979
},
@@ -88,38 +88,38 @@ function getMacosStateMachine(
8888
eventName: StateMachineEvent.FINALIZE,
8989
callback: handlePressOut,
9090
},
91-
]);
91+
];
9292
}
9393

94-
function getUniversalStateMachine(
94+
function getUniversalStatesConfig(
9595
handlePressIn: (event: PressableEvent) => void,
9696
handlePressOut: (event: PressableEvent) => void
9797
) {
98-
return new PressableStateMachine([
98+
return [
9999
{
100100
eventName: StateMachineEvent.FINALIZE,
101101
callback: (event: PressableEvent) => {
102102
handlePressIn(event);
103103
handlePressOut(event);
104104
},
105105
},
106-
]);
106+
];
107107
}
108108

109-
export function getConfiguredStateMachine(
109+
export function getStatesConfig(
110110
handlePressIn: (event: PressableEvent) => void,
111111
handlePressOut: (event: PressableEvent) => void
112-
) {
112+
): StateDefinition[] {
113113
if (Platform.OS === 'android') {
114-
return getAndroidStateMachine(handlePressIn, handlePressOut);
114+
return getAndroidStatesConfig(handlePressIn, handlePressOut);
115115
} else if (Platform.OS === 'ios') {
116-
return getIosStateMachine(handlePressIn, handlePressOut);
116+
return getIosStatesConfig(handlePressIn, handlePressOut);
117117
} else if (Platform.OS === 'web') {
118-
return getWebStateMachine(handlePressIn, handlePressOut);
118+
return getWebStatesConfig(handlePressIn, handlePressOut);
119119
} else if (Platform.OS === 'macos') {
120-
return getMacosStateMachine(handlePressIn, handlePressOut);
120+
return getMacosStatesConfig(handlePressIn, handlePressOut);
121121
} else {
122122
// Unknown platform - using minimal universal setup.
123-
return getUniversalStateMachine(handlePressIn, handlePressOut);
123+
return getUniversalStatesConfig(handlePressIn, handlePressOut);
124124
}
125125
}

0 commit comments

Comments
 (0)