Home > Enterprise >  Understanding react-native navigation
Understanding react-native navigation

Time:03-15

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.

  • Related