react-native-screens
react-native-screens copied to clipboard
react-navigation: App randomly freezes when react-native Modal is shown while preventing remove screen with usePreventRemove on iOS
Description
I have a NativeStackNavigator with 2 screens; on the first screen i have a button to navigate to the second screen; on the second screen, i am using the usePreventRemove hook to show a confirmation modal to the user when i tries to navigate to the previous screen;
import React, {useCallback, useState} from 'react';
import {
NavigationAction,
useIsFocused,
useNavigation,
} from '@react-navigation/native';
import usePreventRemove from '@react-navigation/core/src/usePreventRemove';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {Modal, Text, View, StyleSheet} from 'react-native';
import {Button} from './Button.tsx';
import {Routes} from './StackNavigator.tsx';
export const ExitConfirmModal = () => {
const navigation =
useNavigation<NativeStackNavigationProp<Routes, keyof Routes>>();
const [pendingAction, setPendingAction] = useState<NavigationAction>();
const isFocused = useIsFocused();
const handlePressCancel = useCallback(() => {
setPendingAction(undefined);
}, []);
const handlePressConfirm = useCallback(
(action: NavigationAction) => {
setPendingAction(undefined);
navigation.dispatch(action);
},
[navigation],
);
usePreventRemove(isFocused && !pendingAction, event => {
setPendingAction(event.data.action);
});
if (!pendingAction) {
return null;
}
return (
<Modal
animationType="none"
hardwareAccelerated
transparent
visible
onRequestClose={handlePressCancel}>
<View>
<Button onPress={() => handlePressConfirm(pendingAction)}>
<Text>Go back</Text>
</Button>
<Button onPress={handlePressCancel}>
<Text>Cancel</Text>
</Button>
</View>
</Modal>
);
};
here it is an example of the bug behaviour:
https://github.com/react-navigation/react-navigation/assets/37150312/48ade50f-a6d9-4a3b-bf69-abdcb9736c5c
Steps to reproduce
- open the app
- press "go to second" button to navigate to second screen
- press the back button to go back to previous screen
- when the modal open, press cancel
- repeat step 3
- sometimes the app freezes when the modal appears.
the freeze occurs randomly, so repeating steps from 3 to 5 multiple times is sometimes needed. in order to enhance the chances of the bug to occur, it is useful to run the app on a physical device (iPhone) and repeat steps from 3 to 5 multiple times rapidly. I was able to reproduce the bug only on iOS
Snack or a link to a repository
https://github.com/BadLice/modal-freeze-reproducer
Screens version
3.31.1
React Native version
0.74.1
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
Debug mode
Device
Real device
Device model
iPhone 12
Acknowledgements
Yes
Hey @BadLice, thanks for reporting the issue.
Would you mind to check whether
- #2113
haven't fixed the issue?
As this PR landed already on main you can test it by installing this library from source code by putting following in your package.json:
"react-native-screens": "software-mansion/react-native-screens#main"
hi @kkafar, thank you for your response.
unfortunately, this PR didn't fix my issue;
i created a new branch in my reproducer app resolving this library from main branch, so you can see the issue still persists: https://github.com/BadLice/modal-freeze-reproducer/tree/react-native-screens-main
@BadLice have you tried to pass presentationStyle="overFullScreen" to Modal? This helps sometimes.
Can you try my PR? I think this might fix the issue https://github.com/software-mansion/react-native-screens/pull/2175
hi @hirbod, thanks for your response.
Your PR fixed my issue!
instead, passing presentationStyle="overFullScreen" did not help.
Thank you!
@kkafar I'll prepare a reproducer for you now, but as you can see, my PR solves even more issues :)