1
import React, { useContext, useEffect, useRef } from "react";
import { ScrollView, StyleSheet, Text, View, TouchableOpacity } from "react-native";

// custom components
import Screen from "../components/Screen";

// context api
import { useNavigation } from "@react-navigation/native";

function HomeScreen(props) {
  const navigation = useNavigation();

  useEffect(() => {
    alert("mount");
    
    return () => {
      alert("unmount");
    };
  }, []);

  return (
    <Screen>
      <TouchableOpacity
        onPress={() => navigation.navigate("CategoryList", { name: "Mark" })}
      >
        <Text>Mark</Text>
      </TouchableOpacity>
     
    </Screen>
  );
}

export default HomeScreen;

First this component renders and alert message mount. Now when I navigate into the CategoryList screen, it successfully navigates into the CategoryList screen but, before navigating into the CategoryList screen, this HomeScreen re-renders, alert the messages mount and unmount both, then only it renders CategoryList screen. My question is if we are navigating into the CategoryList screen, then only CategoryList screen should render, isn't it ? Why HomeScreen re-renders then it goes to CategoryList screen. Even from CategoryList screen, if I go into another screen, then again it re-rerenders HomeScreen, then CategoryListScreen then another screen. So, is it the way it works or can we optimize re-renders ?

Navigation structure is like App.js

return (
    <AuthContext.Provider value={{ user, setUser }}>
      <Store> //Store is a context provider where the SafeAreaView below has been passed as children props
        <SafeAreaView style={styles.container}>
          <NavigationContainer theme={navigationTheme}>
            {user ? <AppNavigator /> : <AuthNavigator />}
          </NavigationContainer>
        </SafeAreaView>
      </Store>
    </AuthContext.Provider>
  );

Inside AppNavigator.js

return (
        <Tab.Navigator
            tabBarOptions={{
                showLabel: false,
                activeBackgroundColor: colors.primary,
                activeTintColor: colors.white
            }}
        >
            <Tab.Screen 
                name="Home" 
                component={HomeNavigator}
                options={{
                    tabBarIcon: ({size, color}) => <MaterialCommunityIcons size={size} color={color} name="home"/>
                }}
            />
           
            
        </Tab.Navigator>
    );

Inside HomeNavigator.js

function HomeNavigator(props) {
  const Stack = createStackNavigator();

  const HomeScreenWrapper = () => {
     return (
       <HomeStore>
         <HomeScreen />
       </HomeStore>
     );
   };

// Given above HomeScreenWrapper is a function which returns HomeScreen component wrapping inside HomeStore which is a context provider for HomeScreen only

  return (
    <Stack.Navigator
      screenOptions={{
        headerStyle: {
          backgroundColor: colors.primary,
        },
        headerTintColor: colors.white,
      }}
    >
      <Stack.Screen name="Home" component={HomeScreenWrapper} />
      <Stack.Screen
        name="CategoryList"
        component={CategoryListScreen}
        options={({ route }) => ({
          title: route.params.name,
          headerBackTitleVisible: false,
        })}
      ></Stack.Screen>

    </Stack.Navigator>
  );
}

export default HomeNavigator;

And to see what's inside HomeScreen, Scroll to the top at first.

1 Answer 1

1

You need to read this documentation about react navigation.

Consider a 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.

And this document about react hook.

When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.We’ll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.

If you want to optimise the navigation read this

With the advent of react-native-screens, the native screen optimization is brought possible to React Navigation by bringing the native navigation component (UIViewController for iOS, and FragmentActivity for Android). By using react-native-screens, it is possible for each native platform to optimize the memory usage for screens that are under the view stack and also simplify the native node hierarchy. You can take a look at the comparison here to see the performance gain.

Sign up to request clarification or add additional context in comments.

4 Comments

I've gone through the link you provided. I tried the example in the snack given in that link. I understood how the navigation renders. But mine is not working as expected. What happens is, in the above example, the HomeScreen component mounts and alerts the message mount. Now according to the doc, when I navigate from HomeScreen to CategoryList screen, then HomeScreen should not get unmounted but it does in my case and mount again and then navigates to CategoryScreen. After navigating, alert messages be like unmount, mount, and then it navigates to CategoryList screen.
I cannot help you more because I cannot reproduce the same behavior without looking at the structure of your navigation. When I use your useEffect the alert only show once.
I've added the Navigation structure also. So could you try once, that if you could help to figure out what's the issue?
Yes, I found the issue. The issue was in HomeNavigator. When rendering HomeScreen, I wrapped it inside HomeStore which is the context provider for HomeScreen. But, when I passed just HomeScreen without wrapping inside HomeStore as <Stack.Screen name="Home" component={HomeScreen} /> then it is working as expected.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.