diff --git a/apps/src/tests/Test2175.tsx b/apps/src/tests/Test2175.tsx
new file mode 100644
index 0000000000..dbab010c24
--- /dev/null
+++ b/apps/src/tests/Test2175.tsx
@@ -0,0 +1,151 @@
+import React from 'react';
+import { Button, Modal, SafeAreaView, Text, View } from 'react-native';
+
+import { createNativeStackNavigator } from '@react-navigation/native-stack';
+import { NavigationContainer } from '@react-navigation/native';
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+
+const Stack = createNativeStackNavigator();
+const Tabs = createBottomTabNavigator();
+
+
+function TabScreens({ navigation }): React.JSX.Element {
+ return (
+
+
+
+
+ );
+}
+
+function TabHomeScreen({ navigation }): React.JSX.Element {
+ return (
+
+ Where do you where do you go, my lovely, oh oh oh oh
+
+ )
+}
+
+
+function HomeScreen({ navigation }): React.JSX.Element {
+ const [toggle, setToggle] = React.useState(false);
+ return (
+
+ Where do you where do you go, my lovely, oh oh oh oh
+ { navigation.navigate('TransparentModal') }} />
+ { navigation.navigate('Modal') }} />
+ { navigation.navigate('Tabs') }} />
+ { setToggle(old => !old) }} />
+ setToggle(false)}
+ presentationStyle='formSheet'
+ animationType='slide'
+ >
+
+ Hello I'm a foreign modal
+ { setToggle(false) }} />
+
+
+
+ )
+}
+
+function ModalScreen({ navigation }): React.JSX.Element {
+ const [toggle2, setToggle2] = React.useState(false);
+
+ return (
+
+ Where do you where do you go, my lovely, oh oh oh oh
+ { navigation.goBack() }} />
+
+ { navigation.push('Modal') }} />
+ { navigation.push('ForeignModal')}} />
+ { setToggle2(old => !old )}} />
+ setToggle2(false)}
+ presentationStyle='formSheet'
+ animationType='slide'
+ >
+
+ Hello I'm a foreign modal
+ { setToggle2(false) }} />
+
+
+
+ )
+}
+
+function ForeignModal({ navigation }): React.JSX.Element | null {
+ const [toggle, setToggle] = React.useState(false);
+ return (
+ setToggle(false)}
+ presentationStyle='formSheet'
+ animationType='slide'
+ >
+
+ Hello I'm a foreign modal
+ { setToggle(false) }} />
+
+
+ )
+}
+
+
+const TestScreen = ({ navigation }): React.JSX.Element => {
+ return (
+
+ {
+ console.log(Date.now());
+ }}
+ />
+ {
+ navigation.navigate('Test2');
+ }}
+ />
+
+ );
+};
+
+function App(): React.JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/apps/src/tests/index.ts b/apps/src/tests/index.ts
index f4142428b7..fa45d8ee7f 100644
--- a/apps/src/tests/index.ts
+++ b/apps/src/tests/index.ts
@@ -101,6 +101,7 @@ export { default as Test2028 } from './Test2028';
export { default as Test2048 } from './Test2048';
export { default as Test2069 } from './Test2069';
export { default as Test2118 } from './Test2118';
+export { default as Test2175 } from './Test2175';
export { default as Test2184 } from './Test2184';
export { default as Test2223 } from './Test2223';
export { default as Test2227 } from './Test2227';
diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm
index 8fa4fbb7be..cc26600522 100644
--- a/ios/RNSScreenStack.mm
+++ b/ios/RNSScreenStack.mm
@@ -1273,12 +1273,25 @@ - (void)prepareForRecycle
- (void)invalidate
{
_invalidated = YES;
- for (UIViewController *controller in _presentedModals) {
+ [self dismissAllRelatedModals];
+ [_controller willMoveToParentViewController:nil];
+ [_controller removeFromParentViewController];
+}
+
+// This method aims to dismiss all modals for which presentation process
+// has been initiated in this navigation controller, i. e. either a Screen
+// with modal presentation or foreign modal presented from inside a Screen.
+- (void)dismissAllRelatedModals
+{
+ [_controller dismissViewControllerAnimated:NO completion:nil];
+
+ // This loop seems to be excessive. Above message send to `_controller` should
+ // be enough, because system dismisses the controllers recursively,
+ // however better safe than sorry & introduce a regression, thus it is left here.
+ for (UIViewController *controller in [_presentedModals reverseObjectEnumerator]) {
[controller dismissViewControllerAnimated:NO completion:nil];
}
[_presentedModals removeAllObjects];
- [_controller willMoveToParentViewController:nil];
- [_controller removeFromParentViewController];
}
#endif // RCT_NEW_ARCH_ENABLED
diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx
index 53e28bfb66..e49ed582b4 100644
--- a/src/components/Screen.tsx
+++ b/src/components/Screen.tsx
@@ -373,15 +373,12 @@ export const InnerScreen = React.forwardRef(
// e.g. to use `useReanimatedTransitionProgress` (see `reanimated` folder in repo)
export const ScreenContext = React.createContext(InnerScreen);
-const Screen = React.forwardRef(
- (props, ref) => {
- const ScreenWrapper = React.useContext(ScreenContext) || InnerScreen;
+const Screen = React.forwardRef((props, ref) => {
+ const ScreenWrapper = React.useContext(ScreenContext) || InnerScreen;
- return ;
- }
-);
+ return ;
+});
Screen.displayName = 'Screen';
-
export default Screen;