I created a native Modal using Gesture from react-native-gesture-handler so that the Modal can be closed by swiping down. In iOS, after closing the mode and switching to other screens, the app hangs/closes or needs to be restarted. There is no error in the console, but there is a message in Xcode that the application has stopped.
It looks like it happens when I use the new architecture RCT_NEW_ARCH_ENABLED=1, if disable then it works well
"react-native": "0.74.3",
"react-native-gesture-handler": "^2.18.1",
"react-native-reanimated": "^3.14.0",
"react-native-safe-area-context": "^4.10.7",
"react-native-screens": "^3.32.0",
Root App.tsx
import 'react-native-gesture-handler';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import RootNavigator from './navigation/RootNavigator/RootNavigator';
const App: FC = () => (
<ThemeProvider>
<LocaleProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<RootNavigator />
</SafeAreaProvider>
</GestureHandlerRootView>
</LocaleProvider>
</ThemeProvider>
);
export default App;
CustomModal.tsx
import { PropsWithChildren, useRef } from 'react';
import {
Modal,
Dimensions,
ModalProps,
View,
StyleProp,
ViewStyle,
Platform,
SafeAreaView,
Text
} from 'react-native';
import {
ScrollView,
GestureHandlerRootView,
GestureDetector,
Gesture,
GestureType,
} from 'react-native-gesture-handler';
import { runOnJS, useSharedValue, withSpring } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTheme } from '../../theme';
interface I Modal extends ModalProps {
onClose: () => void;
headerTitle?: string;
scrollEnabled?: boolean;
}
const { height: windowHeight } = Dimensions.get('window');
export function CustomModal({
children,
onClose,
headerTitle,
scrollEnabled,
...props
}: PropsWithChildren<IModal>) {
const { layout, gutters, colors, borders, fonts, navigationTheme } =
useTheme();
const translateY = useSharedValue(0);
const insets = useSafeAreaInsets();
const simultaneousRef = useRef<GestureType | undefined>(undefined);
const scrollViewRef = useRef<ScrollView | null>(null);
const panGesture = Gesture.Pan()
.onUpdate((event) => {
translateY.value = event.translationY;
})
.onEnd((event) => {
if (event.translationY > windowHeight / 4) {
runOnJS(onClose)();
} else {
translateY.value = withSpring(0);
}
})
.simultaneousWithExternalGesture(scrollViewRef)
.withRef(simultaneousRef);
const contentContainerStyle: ViewStyle[] = [
layout.flexGrow_1,
gutters.paddingHorizontal_16,
];
return (
<Modal
animationType="slide"
onRequestClose={onClose}
presentationStyle="pageSheet"
transparent={false}
{...props}
>
<GestureHandlerRootView style={[layout.flex_1]}>
<SafeAreaView style={[layout.flex_1]}>
<GestureDetector gesture={panGesture}>
<View
style={[
layout.fullHeight,
layout.fullWidth,
gutters.paddingTop_10,
]}
>
<View
style={[
layout.row,
layout.itemsCenter,
layout.justifyBetween,
gutters.paddingVertical_16,
]}
>
<View style={[layout.flex_1]}>
<Text
numberOfLines={1}
style={[fonts.center, fonts.size_18, fonts.lineHeight_22]}
>
{headerTitle}
</Text>
</View>
<View style={[layout.flex_05, gutters.marginLeft_4]} />
</View>
<ScrollView
ref={scrollViewRef}
contentContainerStyle={contentContainerStyle}
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="handled"
nestedScrollEnabled
scrollEnabled={scrollEnabled}
simultaneousHandlers={simultaneousRef}
>
{children}
</ScrollView>
</View>
</GestureDetector>
</SafeAreaView>
</GestureHandlerRootView>
</Modal>
);
}
Podfile:
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, min_ios_version_supported
prepare_react_native_project!
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'Awesome' do
config = use_native_modules!
use_react_native!(
:path => config[:reactNativePath],
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
target 'AwesomeTests' do
inherit! :complete
# Pods for testing
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
# :ccache_enabled => true
)
end
end