Skip to content

Commit b60257b

Browse files
akwasniewskim-bert
andauthored
Remove begin from StateManager (#4024)
## Description We realised that there is no real use case for allowing to state manage gestures which did not receive touches. Thus we decided to remove the function `GestureStateManager.begin()` altogether, as if gesture had received touches it's state is set to begun. Additonally StateManager will no longer force going through begin state in activate, thus if we attempt to use state manager to activate a non begun gesture it won't activate. ## Test plan Tested on the following example <details> ```tsx import { COLORS, commonStyles } from '../common-app/src/common'; import React from 'react'; import { View } from 'react-native'; import { GestureHandlerRootView, GestureDetector, useLongPressGesture, GestureStateManager, useSimultaneousGestures, usePanGesture, useManualGesture, } from 'react-native-gesture-handler'; import Animated, { useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; export default function TwoPressables() { const isActivated = [useSharedValue(0), useSharedValue(0)]; const lp1 = useLongPressGesture({ onBegin: () => { 'worklet'; console.log("other begin"); }, onActivate: () => { 'worklet'; isActivated[0].value = 1; console.log(`Box 1: long pressed`); }, onFinalize: () => { 'worklet'; console.log("other finalized") isActivated[0].value = 0; }, disableReanimated: true, minDuration: 1000000 }) const lp2 = useManualGesture({ onTouchesDown: () => { console.log("touches down") }, onTouchesUp: (e) => { console.log("touches up") GestureStateManager.deactivate(e.handlerTag) }, onActivate: () => { 'worklet'; isActivated[1].value = 1; GestureStateManager.activate(lp1.handlerTag); console.log(`Box 2: long pressed`); }, onFinalize: () => { 'worklet'; console.log("fhduifhuifhuiwefhuf") isActivated[1].value = 0; }, disableReanimated: true, }) const pan = usePanGesture({ onActivate: () => { 'worklet'; GestureStateManager.activate(lp2.handlerTag); } }) const g2 = useSimultaneousGestures(lp2, pan); const gestures = [] gestures[0] = lp1; gestures[1] = g2; const colors = [COLORS.PURPLE, COLORS.NAVY, COLORS.GREEN, COLORS.RED]; function Box({ index }: { index: number }) { const animatedStyle = useAnimatedStyle(() => ({ opacity: isActivated[index].value === 1 ? 0.5 : 1, transform: [ { scale: withTiming(isActivated[index].value === 1 ? 0.95 : 1) }, ], })); return ( <GestureDetector gesture={gestures[index]}> <Animated.View style={[ commonStyles.box, { backgroundColor: colors[index] }, animatedStyle, ]} /> </GestureDetector> ); } return ( <GestureHandlerRootView> <View style={commonStyles.centerView}> <Box index={0} /> <Box index={1} /> </View> </GestureHandlerRootView> ); } ``` </details> --------- Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
1 parent 0e91d90 commit b60257b

File tree

8 files changed

+15
-44
lines changed

8 files changed

+15
-44
lines changed

packages/docs-gesture-handler/docs/fundamentals/state-manager.mdx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ const styles = StyleSheet.create({
7070

7171
If you want to control gesture lifecycle outside of it, you can use `handlerTag` from created gesture object.
7272

73+
:::note
74+
The gestures can only be activated after it has begun, that is, after it has received received touch events.
75+
:::
76+
7377
<CollapsibleCode
7478
label="Show full example"
7579
expandedLabel="Hide full example"
@@ -179,14 +183,6 @@ const styles = {
179183

180184
`GestureStateManager` provides methods to manipulate gesture's state imperatively.
181185

182-
### begin
183-
184-
```tsx
185-
begin: (handlerTag: number) => void;
186-
```
187-
188-
Triggers [`onBegin`](/docs/fundamentals/callbacks-events#onbegin) callback on gesture with specified `handlerTag`.
189-
190186
### activate
191187

192188
```tsx

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,11 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
145145
UiThreadUtil.assertOnUiThread()
146146

147147
registry.getHandler(handlerTag)?.let { handler ->
148-
if (handler.state == GestureHandler.STATE_UNDETERMINED) {
149-
handler.forceReinitializeDuringOnHandle = true
150-
151-
// When going from UNDETERMINED to ACTIVE, force going through BEGAN to preserve
152-
// the correct state flow
153-
if (newState == GestureHandler.STATE_ACTIVE) {
154-
handler.begin()
148+
if (newState == GestureHandler.STATE_ACTIVE) {
149+
if (handler.state != GestureHandler.STATE_BEGAN) {
150+
// We don't allow activation of gestures which haven't received any touches
151+
return
155152
}
156-
}
157-
158-
if (newState == GestureHandler.STATE_ACTIVE || newState == GestureHandler.STATE_BEGAN) {
159153
handler.recordHandlerIfNotPresent()
160154
}
161155

packages/react-native-gesture-handler/apple/RNGestureHandler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
@property (nonatomic, weak, nullable) RNGHUIView *hostDetectorView;
8787
@property (nonatomic, nullable, assign) NSNumber *virtualViewTag;
8888
@property (nonatomic, copy, nullable) NSNumber *viewTag;
89+
@property (nonatomic, readonly) RNGestureHandlerState lastState;
8990

9091
- (BOOL)isViewParagraphComponent:(nullable RNGHUIView *)view;
9192
- (nonnull RNGHUIView *)chooseViewForInteraction:(nonnull UIGestureRecognizer *)recognizer;

packages/react-native-gesture-handler/apple/RNGestureHandlerModule.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ - (void)setGestureStateSync:(int)state forHandler:(int)handlerTag
225225
} else if (state == 3) { // CANCELLED
226226
handler.recognizer.state = RNGHGestureRecognizerStateCancelled;
227227
} else if (state == 4) { // ACTIVE
228-
if (handler.recognizer.state == UIGestureRecognizerStatePossible) {
229-
// Force going from UNDETERMINED to ACTIVE through BEGAN to preserve the correct state transition flow.
230-
[handler handleGesture:handler.recognizer fromReset:NO fromManualStateChange:YES];
228+
// We don't allow activation of gestures which haven't received any touches
229+
if (handler.lastState == RNGestureHandlerStateUndetermined) {
230+
return;
231231
}
232232
[handler stopActivationBlocker];
233233
handler.recognizer.state = RNGHGestureRecognizerStateBegan;

packages/react-native-gesture-handler/src/v3/gestureStateManager.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { State } from '../State';
22
import { tagMessage } from '../utils';
33

44
export type GestureStateManagerType = {
5-
begin(handlerTag: number): void;
65
activate(handlerTag: number): void;
76
fail(handlerTag: number): void;
87
deactivate(handlerTag: number): void;
@@ -21,11 +20,6 @@ const setGestureState = (handlerTag: number, state: State) => {
2120
};
2221

2322
export const GestureStateManager: GestureStateManagerType = {
24-
begin(handlerTag: number) {
25-
'worklet';
26-
setGestureState(handlerTag, State.BEGAN);
27-
},
28-
2923
activate(handlerTag: number) {
3024
'worklet';
3125
setGestureState(handlerTag, State.ACTIVE);

packages/react-native-gesture-handler/src/v3/gestureStateManager.web.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { State } from '../State';
21
import { tagMessage } from '../utils';
32
import IGestureHandler from '../web/handlers/IGestureHandler';
43
import GestureHandlerOrchestrator from '../web/tools/GestureHandlerOrchestrator';
@@ -16,24 +15,10 @@ function ensureHandlerAttached(handler: IGestureHandler) {
1615
}
1716

1817
export const GestureStateManager: GestureStateManagerType = {
19-
begin(handlerTag: number): void {
20-
'worklet';
21-
const handler = NodeManager.getHandler(handlerTag);
22-
ensureHandlerAttached(handler);
23-
24-
GestureHandlerOrchestrator.instance.recordHandlerIfNotPresent(handler);
25-
handler.begin();
26-
},
27-
2818
activate(handlerTag: number): void {
2919
'worklet';
3020
const handler = NodeManager.getHandler(handlerTag);
3121
ensureHandlerAttached(handler);
32-
// Force going from UNDETERMINED to ACTIVE through BEGAN to preserve
33-
// the correct state transition flow.
34-
if (handler.state === State.UNDETERMINED) {
35-
handler.begin();
36-
}
3722

3823
GestureHandlerOrchestrator.instance.recordHandlerIfNotPresent(handler);
3924
handler.activate(true);

packages/react-native-gesture-handler/src/web/handlers/GestureHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ export default abstract class GestureHandler implements IGestureHandler {
228228
public activate(force = false) {
229229
if (
230230
(this.manualActivation !== true || force) &&
231-
(this.state === State.UNDETERMINED || this.state === State.BEGAN)
231+
this.state === State.BEGAN
232232
) {
233233
this.delegate.onActivate();
234234
this.moveToState(State.ACTIVE);

skills/gesture-handler-3-migration/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ In Gesture Handler 3, `stateManager` is no longer passed to `TouchEvent` callbac
6969

7070
`GestureStateManager` provides methods for imperative state management:
7171

72-
- .begin(handlerTag: number)
7372
- .activate(handlerTag: number)
7473
- .deactivate(handlerTag: number) (.end() in the old API)
7574
- .fail(handlerTag: number)
@@ -81,6 +80,8 @@ In Gesture Handler 3, `stateManager` is no longer passed to `TouchEvent` callbac
8180

8281
Callback definitions CANNOT reference the gesture that's being defined. In this scenario use events to get access to the handler tag.
8382

83+
Remove GestureStateManager.begin() as gestures must now automatically enter the BEGAN state via touch events before they can be activated through the GestureStateManager.
84+
8485
### Migrating relations
8586

8687
#### Composed gestures

0 commit comments

Comments
 (0)