diff --git a/apps/src/tests/Test1645.js b/apps/src/tests/Test1645.js
new file mode 100644
index 0000000000..ec4a508944
--- /dev/null
+++ b/apps/src/tests/Test1645.js
@@ -0,0 +1,98 @@
+/* eslint-disable react-native/no-inline-styles */
+
+import React, {useEffect, useState} from 'react';
+import {Text, View} from 'react-native';
+
+import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
+import {createNativeStackNavigator} from '@react-navigation/native-stack';
+import {createStackNavigator} from '@react-navigation/stack';
+import {NavigationContainer} from '@react-navigation/native';
+
+const TestBottomTabBar = createBottomTabNavigator();
+const TestNativeStack1 = createNativeStackNavigator();
+const TestNativeStack2 = createNativeStackNavigator();
+
+const TestScreen1 = () => {
+ const [t, setT] = useState(110);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setT(lastT => lastT + 1);
+ }, 100);
+
+ return () => clearInterval(interval);
+ }, []);
+ return (
+
+ {Array.from({length: 100}).map((e, idx) => (
+
+ T{idx}: {t}
+
+ ))}
+
+ );
+};
+
+const TestScreen2 = () => {
+ const [t, setT] = useState(0);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setT(lastT => lastT + 1);
+ }, 100);
+
+ return () => clearInterval(interval);
+ }, []);
+
+ return (
+
+ {Array.from({length: 100}).map((e, idx) => (
+
+ T{idx}: {t}
+
+ ))}
+
+ );
+};
+const TestScreenTab1 = () => {
+ return (
+
+
+
+
+ );
+};
+
+const TestScreenTab2 = () => {
+ return (
+
+
+
+
+ );
+};
+
+const App = () => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default App;
diff --git a/apps/src/tests/Test432.tsx b/apps/src/tests/Test432.tsx
new file mode 100644
index 0000000000..5a0843dbc0
--- /dev/null
+++ b/apps/src/tests/Test432.tsx
@@ -0,0 +1,72 @@
+import { Pressable, View, Button, Text } from 'react-native';
+
+import { NavigationContainer, useNavigation } from '@react-navigation/native';
+import {
+ NativeStackScreenProps,
+ createNativeStackNavigator,
+} from '@react-navigation/native-stack';
+import React, { useCallback } from 'react';
+
+type RootStackParamList = {
+ Home: undefined;
+ Settings: undefined;
+};
+type RootStackScreenProps =
+ NativeStackScreenProps;
+const HomeScreen = ({ navigation }: RootStackScreenProps<'Home'>) => {
+ const showSettings = useCallback(() => {
+ navigation.navigate('Settings');
+ }, [navigation]);
+ return (
+
+
+
+ );
+};
+
+const SettingsScreen = ({ navigation }: RootStackScreenProps<'Settings'>) => {
+ return (
+
+ Settings
+
+ );
+};
+
+const RootStack = createNativeStackNavigator();
+const RootNavigator = () => {
+ const navigation = useNavigation();
+ const headerRight = useCallback(
+ () => (
+ {
+ navigation.goBack();
+ }}>
+ Close
+
+ ),
+ [navigation],
+ );
+ return (
+
+
+
+
+ );
+};
+
+export default function App() {
+ return (
+
+
+
+ );
+}
diff --git a/apps/src/tests/index.ts b/apps/src/tests/index.ts
index eac3106dc2..ff4c9e2baa 100644
--- a/apps/src/tests/index.ts
+++ b/apps/src/tests/index.ts
@@ -5,6 +5,7 @@ export { default as Test111 } from './Test111';
export { default as Test263 } from './Test263';
export { default as Test349 } from './Test349';
export { default as Test364 } from './Test364';
+export { default as Test432 } from './Test432';
export { default as Test528 } from './Test528';
export { default as Test550 } from './Test550';
export { default as Test556 } from './Test556';
@@ -81,6 +82,7 @@ export { default as Test1473 } from './Test1473';
export { default as Test1476 } from './Test1476';
export { default as Test1509 } from './Test1509';
export { default as Test1539 } from './Test1539';
+export { default as Test1645 } from './Test1645';
export { default as Test1646 } from './Test1646';
export { default as Test1649 } from './Test1649';
export { default as Test1671 } from './Test1671';
diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm
index 7c5b6968ba..934d2f77fc 100644
--- a/ios/RNSScreenStack.mm
+++ b/ios/RNSScreenStack.mm
@@ -118,7 +118,6 @@ @implementation RNSScreenStackView {
BOOL _invalidated;
BOOL _isFullWidthSwiping;
UIPercentDrivenInteractiveTransition *_interactionController;
- BOOL _hasLayout;
__weak RNSScreenStackManager *_manager;
BOOL _updateScheduled;
#ifdef RCT_NEW_ARCH_ENABLED
@@ -142,7 +141,6 @@ - (instancetype)initWithFrame:(CGRect)frame
- (instancetype)initWithManager:(RNSScreenStackManager *)manager
{
if (self = [super init]) {
- _hasLayout = NO;
_invalidated = NO;
_manager = manager;
[self initCommonProps];
@@ -272,18 +270,9 @@ - (void)didMoveToWindow
- (void)maybeAddToParentAndUpdateContainer
{
BOOL wasScreenMounted = _controller.parentViewController != nil;
-#ifdef RCT_NEW_ARCH_ENABLED
- BOOL isScreenReadyForShowing = self.window;
-#else
- BOOL isScreenReadyForShowing = self.window && _hasLayout;
-#endif
- if (!isScreenReadyForShowing && !wasScreenMounted) {
- // We wait with adding to parent controller until the stack is mounted and has its initial
- // layout done.
- // If we add it before layout, some of the items (specifically items from the navigation bar),
- // won't be able to position properly. Also the position and size of such items, even if it
- // happens to change, won't be properly updated (this is perhaps some internal issue of UIKit).
- // If we add it when window is not attached, some of the view transitions will be bloced (i.e.
+ if (!self.window && !wasScreenMounted) {
+ // We wait with adding to parent controller until the stack is mounted.
+ // If we add it when window is not attached, some of the view transitions will be blocked (i.e.
// modal transitions) and the internal view controler's state will get out of sync with what's
// on screen without us knowing.
return;
@@ -1076,7 +1065,6 @@ - (void)didUpdateReactSubviews
// set yet, however the layout call is already enqueued on ui thread. Enqueuing update call on the
// ui queue will guarantee that the update will run after layout.
dispatch_async(dispatch_get_main_queue(), ^{
- self->_hasLayout = YES;
[self maybeAddToParentAndUpdateContainer];
});
}