diff --git a/TestsExample/App.js b/TestsExample/App.js
index 8e04dd995a..e81f44c3e9 100644
--- a/TestsExample/App.js
+++ b/TestsExample/App.js
@@ -76,6 +76,7 @@ import Test1227 from './src/Test1227';
import Test1228 from './src/Test1228';
import Test1259 from './src/Test1259';
import Test1260 from './src/Test1260';
+import Test1299 from './src/Test1299';
enableFreeze(true);
diff --git a/TestsExample/src/Test1299.tsx b/TestsExample/src/Test1299.tsx
new file mode 100644
index 0000000000..5104f4da86
--- /dev/null
+++ b/TestsExample/src/Test1299.tsx
@@ -0,0 +1,62 @@
+import * as React from 'react';
+import { View, StyleSheet, Button } from 'react-native';
+import { createNativeStackNavigator } from 'react-native-screens/native-stack';
+import { NavigationContainer, useNavigation } from '@react-navigation/native';
+
+export const Modal1 = React.memo(() => {
+ return ;
+});
+
+export const Modal2 = React.memo(() => {
+ return (
+
+ );
+});
+export const MainScreen = React.memo(() => {
+ const navigation = useNavigation();
+ return (
+
+
+ );
+});
+
+const Stack = createNativeStackNavigator();
+
+export default function App() {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ backgroundColor: '#ecf0f1',
+ },
+});
diff --git a/ios/RNSScreenStack.m b/ios/RNSScreenStack.m
index 9548ff7224..47c8f8da35 100644
--- a/ios/RNSScreenStack.m
+++ b/ios/RNSScreenStack.m
@@ -142,6 +142,10 @@ - (void)presentationControllerDidDismiss:(UIPresentationController *)presentatio
// that can handle it when dismissing a modal, the same for orientation
[RNSScreenWindowTraits updateWindowTraits];
[_presentedModals removeObject:presentationController.presentedViewController];
+ // we double check if there are no new controllers pending to be presented since someone could
+ // have tried to push another one during the transition
+ _updatingModals = NO;
+ [self updateContainer];
if (self.onFinishTransitioning) {
// instead of directly triggering onFinishTransitioning this time we enqueue the event on the
// main queue. We do that because onDismiss event is also enqueued and we want for the transition
@@ -362,6 +366,14 @@ - (void)setModalViewControllers:(NSArray *)controllers
BOOL shouldAnimate = lastModal && [next isKindOfClass:[RNSScreen class]] &&
((RNSScreenView *)next.view).stackAnimation != RNSScreenStackAnimationNone;
+ // if you want to present another modal quick enough after dismissing the previous one,
+ // it will result in wrong changeRootController, see repro in
+ // https://github.com/software-mansion/react-native-screens/issues/1299 We call `updateContainer` again in
+ // `presentationControllerDidDismiss` to cover this case and present new controller
+ if (previous.beingDismissed) {
+ return;
+ }
+
[previous presentViewController:next
animated:shouldAnimate
completion:^{