Skip to content

Commit ae3196d

Browse files
authored
fix(iOS,Fabric): fix sporadic exiting screen content jump on goBack action (#2838)
## Description Fixes #2538 From time to time the **snapshot** of exiting screen would receive bad frame from the OS during the transition resulting in the visual bug depicted in #2538 and on video down below :point_down:. Basically what happens is described by logs present on the recording below. In JS initiated back transition we exchange the `screenView` with its snapshot & the snapshot **sometimes** receives UIKit-originated frame with origin at `(0, 0)`. I guess it happens only sporadically, because there is some race condition, between animation & layout depending on whether the navigation bar is still attached in the model tree or not. There is no issue in natively initiated back transition. https://github.com/user-attachments/assets/d9d90cac-4507-44ff-bda1-619b71b5da56 ## Changes I've decided to go with setting the snapshot frame directly on creation. Given that the `screenView` has correct frame set (with header height taken into account), the snapshot will have correct frame. ## Test code and steps to reproduce I've added simple `Test2538`, which you can test by going back and forth between screens. With the patch applied I haven't seen the issue even once. ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
1 parent f44fe9c commit ae3196d

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

apps/src/tests/Test2538.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { NavigationContainer, ParamListBase } from '@react-navigation/native';
2+
import { NativeStackNavigationProp, createNativeStackNavigator } from '@react-navigation/native-stack';
3+
import React from 'react';
4+
import { Button, Text, View } from 'react-native';
5+
6+
const Stack = createNativeStackNavigator();
7+
8+
type RouteNavProps = {
9+
navigation: NativeStackNavigationProp<ParamListBase>;
10+
}
11+
12+
function Home({ navigation }: RouteNavProps) {
13+
return (
14+
<View style={{ flex: 1, backgroundColor: 'lightgreen' }}>
15+
<Text>Home screen</Text>
16+
<Button title="Go second" onPress={() => navigation.navigate('Second')} />
17+
</View>
18+
);
19+
}
20+
21+
function Second({ navigation }: RouteNavProps) {
22+
return (
23+
<View style={{ flex: 1, backgroundColor: 'lightblue' }}>
24+
<Text>Second screen</Text>
25+
<Button title="Go back" onPress={() => navigation.goBack()} />
26+
</View>
27+
);
28+
}
29+
30+
function App() {
31+
return (
32+
<NavigationContainer>
33+
<Stack.Navigator>
34+
<Stack.Screen name="Home" component={Home} />
35+
<Stack.Screen name="Second" component={Second} />
36+
</Stack.Navigator>
37+
</NavigationContainer>
38+
);
39+
}
40+
41+
export default App;

apps/src/tests/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export { default as Test2332 } from './Test2332';
118118
export { default as Test2379 } from './Test2379';
119119
export { default as Test2395 } from './Test2395';
120120
export { default as Test2466 } from './Test2466';
121+
export { default as Test2538 } from './Test2538';
121122
export { default as Test2552 } from './Test2552';
122123
export { default as Test2611 } from './Test2611';
123124
export { default as Test2631 } from './Test2631';

ios/RNSScreen.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,6 +1914,7 @@ - (void)setViewToSnapshot
19141914
// if we dismissed the view natively, it will already be detached from view hierarchy
19151915
if (self.view.window != nil) {
19161916
UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO];
1917+
snapshot.frame = self.view.frame;
19171918
[self.view removeFromSuperview];
19181919
self.view = snapshot;
19191920
[superView addSubview:snapshot];

0 commit comments

Comments
 (0)