From 913fdbb51162d788dadcadbaec7c48a6735b4941 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Du=C5=BCy?=
<91994767+alduzy@users.noreply.github.com>
Date: Mon, 7 Oct 2024 22:23:31 +0200
Subject: [PATCH] fix(iOS): header subviews layout on tab change (#2385)
## Description
This PR intents to fix header subviews incorrect layout when changing
tabs.
The previous solution did layout the subviews correctly in the test
cases, but triggered an undesirable `layoutIfNeeded` when going back
from tab to tab. In such case the navigation layout happened without
updating subview's layout metrics.
Moving the logic to subview resolves the issue as the re-layout is now
triggered only when subview's layout metrics are updated.
Related fixes from the past:
https://github.com/software-mansion/react-native-screens/pull/2316,
https://github.com/software-mansion/react-native-screens/pull/2248
## Changes
- combined `Test2231.tsx` with `Test432.tsx` to create comprehensive
test case
- moved re-layout logic to subview
## Screenshots / GIFs
### Before
![Screenshot 2024-10-04 at 10 10
15](https://github.com/user-attachments/assets/1a8a747e-fe1d-4b03-ba63-1891732d7d77)
### After
![Screenshot 2024-10-04 at 10 09
37](https://github.com/user-attachments/assets/68b3554f-d67d-47f4-946d-ace60e1bbf83)
## Test code and steps to reproduce
- Use `Test432.tsx` repro
## Checklist
- [x] Included code example that can be used to test this change
- [x] Ensured that CI passes
---
apps/src/tests/Test2231.tsx | 56 ------------
apps/src/tests/Test432.tsx | 137 +++++++++++++++++++----------
apps/src/tests/index.ts | 1 -
ios/RNSScreenStackHeaderConfig.mm | 3 -
ios/RNSScreenStackHeaderSubview.mm | 24 +++++
5 files changed, 115 insertions(+), 106 deletions(-)
delete mode 100644 apps/src/tests/Test2231.tsx
diff --git a/apps/src/tests/Test2231.tsx b/apps/src/tests/Test2231.tsx
deleted file mode 100644
index 9449ffc3ff..0000000000
--- a/apps/src/tests/Test2231.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
-import React, { useLayoutEffect, useState } from 'react';
-import { View } from 'react-native';
-
-import { SettingsSwitch, Square } from '../shared';
-import { NavigationContainer } from '@react-navigation/native';
-
-const SettingsScreen = ({ navigation }: any) => {
- const [hasLeftItem, setHasLeftItem] = useState(false);
-
- const square1 = (props: { tintColor?: string }) => (
-
- {hasLeftItem && }
-
-
- );
-
- const square2 = (props: { tintColor?: string }) => (
-
- );
-
- useLayoutEffect(() => {
- navigation.setOptions({
- headerRight: square1,
- headerTitle: undefined,
- headerLeft: hasLeftItem ? square2 : undefined,
- headerBackTitleVisible: false,
- });
- }, [navigation, hasLeftItem]);
-
- return (
-
- );
-};
-
-const Stack = createNativeStackNavigator();
-
-const App = () => (
-
-
-
-
-
-);
-
-export default App;
diff --git a/apps/src/tests/Test432.tsx b/apps/src/tests/Test432.tsx
index 8274bfd299..f58bd3b752 100644
--- a/apps/src/tests/Test432.tsx
+++ b/apps/src/tests/Test432.tsx
@@ -1,37 +1,36 @@
-import { Pressable, View, Button, Text } from 'react-native';
-
-import { NavigationContainer, useNavigation } from '@react-navigation/native';
+import { View, Button, Text } from 'react-native';
+import { NavigationContainer } from '@react-navigation/native';
import {
NativeStackScreenProps,
createNativeStackNavigator,
} from '@react-navigation/native-stack';
-import React, { useCallback } from 'react';
+import React, { useEffect, useLayoutEffect, useState } from 'react';
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import { Square } from '../shared';
-type RootStackParamList = {
+type StackParamList = {
Home: undefined;
+ Details: undefined;
Settings: undefined;
+ Info: undefined;
};
-type RootStackScreenProps =
- NativeStackScreenProps;
-const HomeScreen = ({ navigation }: RootStackScreenProps<'Home'>) => {
- const [x, setX] = React.useState(false);
- React.useEffect(() => {
- navigation.setOptions({
- headerBackVisible: !x,
- headerRight: x
- ? () => (
-
- )
- : () => (
-
- ),
- });
- }, [navigation, x]);
+type StackScreenProps = NativeStackScreenProps<
+ StackParamList,
+ T
+>;
+const HomeScreen = ({ navigation }: StackScreenProps<'Home'>) => {
return (
-