Skip to content

Commit 4614e61

Browse files
authored
[Android] Fix crash with RN Screens FormSheet (#4243)
## Description `DimmingView` from React Native Screens implements `ReactCompoundViewGroup`, which implements `ReactCompoundView`. However, this component is managed entirely by Screens, so [`reactTagForTouch` throws when called](https://github.com/software-mansion/react-native-screens/blob/8608eb2b080fb5ee1e1c1ce6a40e3c89c41a37f7/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingView.kt#L66). This causes crash when `Orchestrator` tries to obtain `tag` (see [here](https://github.com/software-mansion/react-native-gesture-handler/blob/9a9f8b41ef54038508fec4cd48495b939a324624/packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt#L581)). To prevent that we add `try/catch` block. Note that simply checking for `ReactViewGroup` wouldn't work, as [`Text` is not `ReactViewGroup`](https://github.com/facebook/react-native/blob/df0d7dece6cdec384c25cdbdff86328bfbee991f/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java#L55). There are also other components in Screens, which do not inherit from `ReactViewGroup`, but from `ViewGroup` instead. Fixes #4237 ## Test plan expo-example app (Nested Text and SVG) <details> <summary>The following code:</summary> ```tsx import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { Button, Platform, StyleSheet, Text, View } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { enableScreens } from 'react-native-screens'; enableScreens(true); const Stack = createNativeStackNavigator(); function HomeScreen({ navigation }) { return ( <View style={styles.screen}> <View style={styles.card}> <Text style={styles.title}>Android formSheet repro</Text> <Text style={styles.body}> This app uses Expo 56 bare workflow with react-native-screens 4.25.2. Press the button to present a native-stack screen with presentation set to formSheet. </Text> <Button title="Open form sheet" onPress={() => navigation.navigate('FormSheet')} /> </View> </View> ); } function FormSheetScreen({ navigation }) { return ( <View style={styles.sheet}> <Text style={styles.sheetTitle}>Form sheet content</Text> <Text style={styles.body}> This is a modal form sheet presented by react-native-screens through React Navigation native stack on {Platform.OS}. </Text> <View style={styles.spacer} /> <Button title="Close sheet" onPress={() => navigation.goBack()} /> </View> ); } export default function App() { return ( <GestureHandlerRootView style={styles.root}> <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} options={{ title: 'FormSheet Repro' }} /> <Stack.Screen name="FormSheet" component={FormSheetScreen} options={{ title: 'Form Sheet', presentation: 'formSheet', sheetAllowedDetents: [0.45, 0.8], sheetCornerRadius: 24, sheetGrabberVisible: true, }} /> </Stack.Navigator> </NavigationContainer> </GestureHandlerRootView> ); } const styles = StyleSheet.create({ root: { flex: 1, }, screen: { flex: 1, backgroundColor: '#f4f6fb', alignItems: 'center', justifyContent: 'center', padding: 24, }, card: { width: '100%', maxWidth: 420, borderRadius: 24, backgroundColor: '#fff', padding: 24, shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 18, elevation: 4, }, title: { marginBottom: 12, color: '#111827', fontSize: 28, fontWeight: '700', }, sheet: { flex: 1, justifyContent: 'center', padding: 24, backgroundColor: '#fff', }, sheetTitle: { marginBottom: 12, color: '#111827', fontSize: 24, fontWeight: '700', }, body: { marginBottom: 24, color: '#4b5563', fontSize: 16, lineHeight: 24, }, spacer: { height: 12, }, }); ``` </details>
1 parent 62d0d52 commit 4614e61

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,15 @@ class GestureHandlerOrchestrator(
578578
}
579579

580580
if (view is ReactCompoundView) {
581-
val tagForCoords = view.reactTagForTouch(coords[0], coords[1])
581+
// Some implementations (e.g. RNScreens' DimmingView) intentionally throw from `reactTagForTouch`
582+
val tagForCoords =
583+
try {
584+
view.reactTagForTouch(coords[0], coords[1])
585+
} catch (e: IllegalStateException) {
586+
null
587+
}
582588

583-
if (tagForCoords != view.id) {
589+
if (tagForCoords != null && tagForCoords != view.id) {
584590
handlerRegistry.getHandlersForViewWithTag(tagForCoords)?.let {
585591
synchronized(it) {
586592
for (handler in it) {

0 commit comments

Comments
 (0)