software-mansion/react-native-gesture-handler

Expo app crashes when using GestureDetector

Ever-It-Lazy opened this issue · 9 comments

Description

I am coding an Expo app that uses @react-navigation/native-stack for navigation and react-native-gesture-handler to track gesture on one screen. It loads fine, but completing the Gesture.Tap() (which should navigate to another screen) crashes Expo.

(This issue bares a vague resemblance to 2840, but I've investigated: they appear to be different.)

Steps to reproduce

I provide a repo as a simple example.

  • The App.js contains a NavigationContainer for 2 screens.
  • The GestureScreen.js contains the Gesture.Tap() example.
  • The OtherScreen.js is simply some other screen to navigate to, no serious functionality.

Snack or a link to a repository

https://github.com/Ever-It-Lazy/gesture_example

Gesture Handler version

2.14.0

React Native version

0.73.6

Platforms

iOS

JavaScript runtime

None

Workflow

Expo managed workflow

Architecture

None

Build type

None

Device

iOS simulator

Device model

iPhone X (iOS 16.7.7)

Acknowledgements

Yes

Hi @Ever-It-Lazy! Thanks to expo team I was able to identify what causes this problem. The error here was missing runOnJS. Gesture callbacks are automatically workletized, but navigation runs on JS thread - therefore you were trying to call non-worklet function on the UI thread.

I've also made some adjustments in your code:

App.js

<Stack.Screen name="GestureScreen" component={GestureScreen} />

You don't have to use gestureHandlerRootHOC if you already have GestureHandlerRootView on the GestureScreen

GestureScreen.js

export default function StartScreen({ navigation }) {
  const doubleTap = Gesture.Tap()
    .numberOfTaps(2)
    .onEnd(() => {
      navigation.navigate("OtherScreen");
    })
    .runOnJS(true);

  return (
    <GestureHandlerRootView style={styles.container}>
      <GestureDetector gesture={doubleTap}>
        <View style={styles.button}>
          <Text style={styles.buttonLabel}>
            Double Tap to go to the other screen
          </Text>
        </View>
      </GestureDetector>
    </GestureHandlerRootView>
  );
}

Here I've changed few things:

  • added runOnJS - it is necessary to resolve this issue, otherwise your app will crash.
  • changed onStart to onEnd - it is much cleaner to use onEnd in that case. Even though Tap is descrete gesture and it will end right after activation, onEnd guarantees that gesture ended successfully.
  • changed Pressable to View - I think it can be confusing that you have gestures applied to Pressable (though it shouldn't break anything if you don't use callbacks on Pressable)

So overall, to get rid of this problem you have to add runOnJS(true) to the gesture builder. Let me know if it helps!

That solved it. Thanks for the other best practices suggestions, as well!

Hi, I'm facing the same issue with my app (RN 0.73.6, RNGH 2.16, Reanimated 3.10 & Expo 50, Fabric ON)

I made a sample project using same stack (without Expo) to reproduce the issue with a simple case and the app crash on view using the GestureDetector even if I add .runOnJS(true).

Here is the sample app => https://github.com/Under-Warz/rngh_sample/blob/main

If anyone have an idea ?

PS : I can't update our app to RN 0.74 because of Expo 50 which is not supported on 0.74 and we have to wait for Expo 51

Hi @Under-Warz! I've just run your sample app on both, Android emulator and iOS simulator - both work fine. Moreover, there's no need to add runOnJS in that case. Could you show some error logs?

thank's @m-bert for you test. Could you give me your version of xcode & ios you are using for the test ? I can't understand why it's crashing here...

The only log message from Xcode when the app crash is

Assertion failed: (hasNativeState<T>(runtime)), function getNativeState, file jsi-inl.h, line 220.
Message from debugger: Terminated due to signal 6

@m-bert just to be sure, did you install the pods with RCT_NEW_ARCH_ENABLED=1 because I didn't setup the Android to use new arch on the sample project.

did you install the pods with RCT_NEW_ARCH_ENABLED=1

I've checked that on old architecture, but I will look into it

Could you give me your version of xcode & ios you are using for the test ?

I've just got Xcode update to version 15.4 and iOS to 17.5, I'll check if it still works for me (also on new arch) and get back to you

I've just realized that I missed Fabric ON in your first message, sorry about that! We found out what causes this issue. However, we also decided that we will support new architecture from RN 0.74, therefore we won't be adding backward compatibility.

I've also noticed that even with a quick fix, your app crashes on hot reload because of Reanimated (the same case here - it should be fine on 0.74)

Thank's for your investigation @m-bert. We've planned to update RN 0.74 & Expo 51 next week.