I am wondering if react removes the components from its memory when you click goback
or navigation.pop()
I am using navigation.Push
and not navigation.navigate
in this case.
Will there be any problems in memory and performance ?
Do I have to do somthing special to clear those ?
CodePudding user response:
In the react-native-navigation lifecycle a screen will remain mounted if you navigate away from a screen that you pushed on the Stack
.
Consider a native stack navigator with screens A and B. After navigating to A, its componentDidMount is called. When pushing B, its componentDidMount is also called, but A remains mounted on the stack and its componentWillUnmount is therefore not called.
On the other hand.
When going back from B to A, componentWillUnmount of B is called, but componentDidMount of A is not because A remained mounted the whole time.
We can test this by creating a simple StackNavigator
with two screens as in the documentation. Create a useEffect
with an empty dependency array and log something as follows.
import React, {useState, useEffect} from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to ScreenA"
onPress={() => navigation.navigate('ScreenA')}
/>
</View>
);
}
function ScreenA({ navigation, route }) {
useEffect(() => {
console.log("Screen A")
}, [])
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to ScreenB"
onPress={() => navigation.navigate('ScreenB')}
/>
</View>
);
}
function ScreenB({ navigation, route }) {
useEffect(() => {
console.log("Screen B")
},[])
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to ScreenA"
onPress={() => navigation.navigate('ScreenA')}
/>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="ScreenA" component={ScreenA} />
<Stack.Screen name="ScreenB" component={ScreenB} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Consider the following navigation route:
ScreenA
->ScreenB
->ScreenA
->ScreenB
We will notice the following log messages:
ScreenA
,ScreenB
,ScreenB
This is because ScreenA remains mounted while ScreenB is unmounted and mounted again.
Now, what happens if we push
a screen? We can test this as well by using the same example but pushing ScreenB in ScreenB itself
as follows.
function ScreenB({ navigation, route }) {
useEffect(() => {
console.log("Screen B")
},[])
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Push to ScreenB"
onPress={() => navigation.push('ScreenB')}
/>
</View>
);
}
We will notice that on each push
a new ScreenB
is mounted!
What happens if we use navigation.pop
? The screen that is being poped
will be unmounted and the same will happen if we use goBack
for the same reasons as provided above.
Performance-wise, using navigation.pop()
or navigation.goBack()
will release the memory of the screen in which we are calling these functions as they are unmounted.
On the other hand, constantly pushing the same screen
on the Stack
is not a good idea.
I would also consider on what code is located in useEffect
. If it is an API call, then we often want it to be only called once. From that perspective it is desired that a screen remains mounted once we have entered it.
To summarize, goBack
and pop
will unmount the screen on which we are calling these functions. React native will release the memory occupied by the screen (in form of states, variables, etc.). You do not have to do anything special.
I have made a little snack using mainly the above code.