software-mansion / software-mansion/react-native-screens
[iOS] App freezes with 100% CPU usage when a touchable is used inside a nested stack's `headerLeft` (repro provided + reproduces consistently)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 3.7k
- Forks
- 714
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 71
Description
Description
When the app has a specific combination of bottom tabs, nested stack navigators and headerLeft, it can freeze and stop responding to input. The Xcode debugger shows 100% CPU usage while the app is frozen.
This only reproduces on iOS < 26. I've verified the issue on simulators with iOS 18.6 and 17.5.
https://github.com/user-attachments/assets/ceceec01-0244-46e8-b2f9-427742ebb390
Steps to reproduce
- Run the code below. ⚠️ Important: run on iOS < 26 to reproduce the bug.
- Press "Navigate to Form screen", then "Navigate to Detail screen", then "Go back".
- Repeat step 2 a few times for good measure. Often doing it once is enough.
- Press on "TabB".
- Observe that the app no longer responds to touches. Observe high CPU usage and an eventual crash.
import { useLayoutEffect } from 'react';
import { Button, ScrollView, Text, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const MainScreen = ({ navigation }) => (
<Button
title="Navigate to Form screen"
onPress={() => navigation.navigate('Form')}
/>
);
const ScrollInnerScreen = () => (
<ScrollView>
{Array.from({ length: 50 }, (_, i) => (
<Text key={i}>{i}</Text>
))}
</ScrollView>
);
const nestedStack = createNativeStackNavigator();
const ScrollScreen = () => (
<nestedStack.Navigator>
<nestedStack.Screen name="ScrollContent" component={ScrollInnerScreen} />
</nestedStack.Navigator>
);
const bottomTabs = createBottomTabNavigator();
const BottomTabsScreen = () => (
<bottomTabs.Navigator initialRouteName="TabA">
<bottomTabs.Screen name="TabA" component={MainScreen} />
<bottomTabs.Screen name="TabB" component={ScrollScreen} />
</bottomTabs.Navigator>
);
const DetailOverviewScreen = ({ navigation }) => {
// Does not reproduce if I remove this
useLayoutEffect(() => {
navigation.setOptions({ headerLeft: () => <TouchableOpacity /> });
}, [navigation]);
return <Button title="Go back" onPress={() => navigation.goBack()} />;
};
const detailStack = createNativeStackNavigator();
const DetailScreen = () => (
<detailStack.Navigator>
<detailStack.Screen
name="DetailOverview"
component={DetailOverviewScreen}
/>
</detailStack.Navigator>
);
const FormScreen = ({ navigation }) => (
<Button
title="Navigate to Detail screen"
onPress={() => navigation.replace('Detail')}
/>
);
const rootStack = createNativeStackNavigator();
const App = () => (
<NavigationContainer>
<rootStack.Navigator>
<rootStack.Screen name="Main" component={BottomTabsScreen} />
<rootStack.Screen name="Detail" component={DetailScreen} />
<rootStack.Screen name="Form" component={FormScreen} />
</rootStack.Navigator>
</NavigationContainer>
);
export default App;
"dependencies": {
"@react-navigation/bottom-tabs": "7.15.10",
"@react-navigation/native": "7.2.2",
"@react-navigation/native-stack": "7.14.12",
"react": "19.2.3",
"react-native": "0.85.2",
"react-native-safe-area-context": "5.7.0",
"react-native-screens": "4.24.0"
}
I couldn't manage to reduce the repro further (e.g. remove bottom tabs) — seems that everything in the above code contributes to the freeze in some way.
Snack or a link to a repository
https://github.com/SimpleCreations/SEE_REPRO_ABOVE_sorry_bot
Screens version
4.24.0
React Native version
0.85.2
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
iOS simulator
Device model
iOS 18.6 simulator
Acknowledgements
Yes
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 reproduction or the linked repository on an iOS simulator below version 26, then follow the navigation sequence through Form, Detail, and TabB. Investigate the interaction between the nested stacks, bottom tabs, and the headerLeft TouchableOpacity set in DetailOverviewScreen. Done means the app remains responsive without sustained 100% CPU usage after repeating the sequence.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react-native
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100