Skip to content

Commit b34a2de

Browse files
authored
Check if handler was dropped before reattaching (#3247)
## Description Currently Gesture Handler crashes apps that use `StrictMode`. ### Problem description `StrictMode` [calls effects twice](https://react.dev/reference/react/StrictMode#fixing-bugs-found-by-re-running-effects-in-development). That means that `attachGestureHandler` and `dropGestureHandler` will be called extra time. However, when `attachGestureHandler` is called for the first time, `view` is not yet initialized. It means that instead of attaching handler, we [schedule another attach later](https://github.com/software-mansion/react-native-gesture-handler/blob/fe66fe168ad102199f06d8365cbf5b20ad24e87e/apple/RNGestureHandlerManager.mm#L170). In the meantime, `dropGestureHandler` removes handler from registry. When we finally try to attach handler one more time, it no longer exists, therefore application crashes. ### Solution While it is not the best solution, we decided to check which handlers were dropped. If we try to reattach already dropped handler, we simply don't do that. On the other hand, if we try to reattach handler that wasn't dropped, app will crash. In other words, we simply reattach handler iff handler has not been dropped before. Fixes #3184 ## Test plan <details> <summary>Tested on the following reproduction:</summary> ```jsx import { StrictMode } from 'react'; import { View } from 'react-native'; import { Gesture, GestureDetector, GestureHandlerRootView, } from 'react-native-gesture-handler'; const Example = () => { const gesture = Gesture.Pan(); return ( <StrictMode> <GestureHandlerRootView> <GestureDetector gesture={gesture}> <View /> </GestureDetector> </GestureHandlerRootView> </StrictMode> ); }; export default Example; ``` </details>
1 parent 39caf79 commit b34a2de

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

apple/RNGestureHandlerManager.mm

+6-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ @implementation RNGestureHandlerManager {
5151
RNGestureHandlerRegistry *_registry;
5252
NSHashTable<RNRootViewGestureRecognizer *> *_rootViewGestureRecognizers;
5353
NSMutableDictionary<NSNumber *, NSNumber *> *_attachRetryCounter;
54+
NSMutableSet *_droppedHandlers;
5455
#ifdef RCT_NEW_ARCH_ENABLED
5556
RCTModuleRegistry *_moduleRegistry;
5657
RCTViewRegistry *_viewRegistry;
@@ -90,6 +91,7 @@ - (void)initCommonProps
9091
_registry = [RNGestureHandlerRegistry new];
9192
_rootViewGestureRecognizers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
9293
_attachRetryCounter = [[NSMutableDictionary alloc] init];
94+
_droppedHandlers = [NSMutableSet set];
9395
}
9496

9597
- (void)createGestureHandler:(NSString *)handlerName tag:(NSNumber *)handlerTag config:(NSDictionary *)config
@@ -168,7 +170,9 @@ - (void)attachGestureHandler:(nonnull NSNumber *)handlerTag
168170
[_attachRetryCounter setObject:counter forKey:viewTag];
169171

170172
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
171-
[self attachGestureHandler:handlerTag toViewWithTag:viewTag withActionType:actionType];
173+
if (![_droppedHandlers containsObject:handlerTag]) {
174+
[self attachGestureHandler:handlerTag toViewWithTag:viewTag withActionType:actionType];
175+
}
172176
});
173177
}
174178

@@ -205,6 +209,7 @@ - (void)updateGestureHandler:(NSNumber *)handlerTag config:(NSDictionary *)confi
205209
- (void)dropGestureHandler:(NSNumber *)handlerTag
206210
{
207211
[_registry dropHandlerWithTag:handlerTag];
212+
[_droppedHandlers addObject:handlerTag];
208213
}
209214

210215
- (void)dropAllGestureHandlers

0 commit comments

Comments
 (0)