software-mansion / software-mansion/react-native-screens
Incorrect orientation shows on screens for roughly 100ms
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 3.7k
- Forks
- 714
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 71
Description
Description
When navigating between screens with different screenOrientation props, there is a roughly 100ms (on my machine) period of time that the incorrect orientation shows. This can be problematic when there are exceptionally heavy javascript computation loads and the screen can show the incorrect orientation for a long period of time, causing a jarring user experience.
Steps To Reproduce
Run the following RN Diff App and notice that it takes roughly 100ms to get the correct orientation from onLayout, whether with a TabNavigator or a StackNavigator:
const React = require('react');
const {
AppRegistry,
Text,
TouchableOpacity,
StyleSheet,
} = require('react-native');
const {
ScreenStack,
Screen,
ScreenContainer,
ScreenStackHeaderConfig,
} = require('react-native-screens');
AppRegistry.registerComponent('RnDiffApp', () => TabApp);
function StackApp() {
const [stackSize, setStackSize] = React.useState(1);
const lastPress = React.useRef(global.nativePerformanceNow());
return (
<ScreenStack style={{flex: 1}}>
{[...Array(stackSize).keys()].map(i => {
const orientation = i % 2 === 0 ? 'portrait' : 'landscape';
return (
<Screen
key={i}
onLayout={e => {
const timeSincePress =
global.nativePerformanceNow() - lastPress.current;
const isCorrect =
orientation === computeOrientation(e.nativeEvent.layout);
if (isCorrect) {
console.log(
`Amount of time rendering the wrong orientation on stack navigator: ${timeSincePress}`,
);
}
}}
style={{...StyleSheet.absoluteFill}}
screenOrientation={orientation}>
<ScreenStackHeaderConfig hidden />
<Text style={{paddingTop: 100}}>Stack Screen {i}</Text>
<TouchableOpacity
onPress={() => {
lastPress.current = global.nativePerformanceNow();
setStackSize(a => a + 1);
}}>
<Text>Click to add a screen</Text>
</TouchableOpacity>
</Screen>
);
})}
</ScreenStack>
);
}
function TabApp() {
const [selectedTab, setSelectedTab] = React.useState(0);
const lastPress = React.useRef(global.nativePerformanceNow());
return (
<ScreenContainer style={{flex: 1}}>
{[0, 1].map(i => {
const orientation = i % 2 === 0 ? 'portrait' : 'landscape';
return (
<Screen
key={i}
activityState={selectedTab === i ? 2 : 0}
onLayout={e => {
const timeSincePress =
global.nativePerformanceNow() - lastPress.current;
const isCorrect =
orientation === computeOrientation(e.nativeEvent.layout);
if (isCorrect) {
console.log(
`Amount of time rendering the wrong orientation on tab navigator: ${timeSincePress}`,
);
}
}}
style={{
...StyleSheet.absoluteFill,
zIndex: selectedTab === i ? 1 : -1,
}}
screenOrientation={orientation}>
<Text style={{paddingTop: 100}}>Tab Screen {i}</Text>
<TouchableOpacity
onPress={() => {
lastPress.current = global.nativePerformanceNow();
setSelectedTab(Number(!selectedTab));
}}>
<Text>Click to go to {orientation}</Text>
</TouchableOpacity>
</Screen>
);
})}
</ScreenContainer>
);
}
function computeOrientation(layout) {
const {width, height} = layout;
return width > height ? 'landscape' : 'portrait';
}
Expected behavior
I would expect onLayout to never fire with the incorrect orientation.
Actual behavior
onLayout does fire with the incorrect orientation.
Reproduction
See code above.
Platform
- iOS
- Android
- Web
- Windows
- tvOS
Workflow
- Managed workflow
- Bare workflow
Package versions
| package | version |
|---|---|
| react-native | 67 |
| @react-navigation/native | |
| @react-navigation/native-stack | |
| react-native-screens | 3.11.0 |
| react-native-safe-area-context | |
| react-native-gesture-handler | |
| react-native-reanimated | |
| expo |
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided React Native reproduction on both iOS and Android, focusing on the screenOrientation and onLayout behavior during navigation. Trace the screen orientation handling in react-native-screens and verify that onLayout does not report the previous orientation after switching screens.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react-native
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100