Prasanga Thapaliya
Prasanga Thapaliya

Reputation: 737

Re-render in react-native. Can we optimize the issue i'm facing?

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.

Upvotes: 1

Views: 444

Answers (1)

docmurloc
docmurloc

Reputation: 1239

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.

Upvotes: 1

Related Questions