Recently I have been building a larger scale project using react-native (0.77.1)without leveraging any framework. i.e. bare-workflow. I faced the known issue, that during sessions of interacting with the app ( mainly navigating ) the application was leaking memory because of navigating in my Stack Navigator's Screens. I am using react-navigation ( https://reactnavigation.org/ ) and have declared my Navigator as the following
<Stack.Navigator detachInactiveScreens={true}>
Even in a tiny dummy application, which I have included below, if ran in XCode and navigated sufficiently ( ~15 times ), the initially required 100mb of memory (RAM) will grow to reach 190mb and continue to grow on further, without ever dropping.
I was thinking it might be caused by the headers not being properly cleared after navigating to a new page, or that perhaps the <Stack.Navigator>
would be saving all of the visited Screens in the background.
Perhaps this is an already resolved issue. But it would be tremendously helpful to continue my project's journey, especially because I am still quite new to react-native. Many Thanks <3
import React from "react";
import { Button, View } from "react-native";
import { enableScreens } from 'react-native-screens';
enableScreens();
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import { SafeAreaProvider } from 'react-native-safe-area-context';
import ScreenOne from "./src/screens/ScreenOne";
import ScreenTwo from "./src/screens/ScreenTwo";
//These are just simple components displaying each a piece of <Text>
export default function App() {
const Stack = createStackNavigator();
return (
<SafeAreaProvider>
<NavigationContainer>
<Stack.Navigator detachInactiveScreens={true}>
<Stack.Screen name="screen-1" component={ScreenOne} options={({navigation}) => ({
headerLeft: () => (
<Button title="go to s2" onPress={() => {
navigation.setOptions({headerLeft: undefined})
navigation.navigate("screen-2")}}/>
)
})}/>
<Stack.Screen name="screen-2" component={ScreenTwo} options={({navigation}) => ({
headerLeft: () => (
<Button title="go to s2" onPress={() => {
navigation.setOptions({headerLeft: undefined})
navigation.navigate("screen-1")}}/>
)
})}/>
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
)
}
I've already tried leveraging the use of useEffect, useMemo, useCallback inside the screen-components, which did not help, as the Navigation is the issue here.
As can be seen, I tried to clear the headerLeft:
parameter on the press of a button. Didn't prove to be effective
Also I tried replacing navigation.navigate(route)
with navigation.replace(route)
, which wasn't successful
I bet your mistake is simply that createStackNavigator()
shall be apart from any component ;
...
import ScreenOne from "./src/screens/ScreenOne";
import ScreenTwo from "./src/screens/ScreenTwo";
const Stack = createStackNavigator();
export default function App() {
return (
<SafeAreaProvider>
...
You might want to take look at the documentation.
Otherwise, you may check out this similar question