Home > Back-end >  React native main component takes 5 seconds to render
React native main component takes 5 seconds to render

Time:03-03

I got a react nativ app to optimize, my problem is that the render method of the main component ALWAYS takes like 5 secondes even when the component is empty (during which the app display a white empty screen). This is a big problem because a 5 sec white screen at the beginning of the app will make the users uninstall the app.

timestamped logs

As you can see here in the logs there is always 5 sec between the rendering of the app and the rendering of the basic navigator with a basic component.

Here is my App.tsx code :

export default function App() {
    // console.info('App: App starting');

    let persistor = persistStore(Store);
    const isLoadingComplete = useCachedResources();

    const loadGeolocation = async () => {
        let { status } = await Location.requestForegroundPermissionsAsync();

        if (status !== "granted") {
            return;
        }
        let geolocation = await Location.getCurrentPositionAsync({});
        Store.dispatch(MobileSlice.actions.setGeolocation(geolocation));
    };

    const load = async () => {
        await Promise.all([loadFonts(), loadGeolocation()]);
    };

    React.useEffect(() => {
        // console.log('App : Loading fonts');
        load();
        // console.log('App : Fonts loaded');
        // initializeRC()
    }, []);

    const onLayoutRootView = React.useCallback(async () => {
        if (isLoadingComplete) {
          // This tells the splash screen to hide immediately! If we call this after
          // `setAppIsReady`, then we may see a blank screen while the app is
          // loading its initial state and rendering its first pixels. So instead,
          // we hide the splash screen once we know the root view has already
          // performed layout.
          await SplashScreen.hideAsync();
        }
      }, [isLoadingComplete]);

    if (!isLoadingComplete) {
        return null;
    } else {
        console.log("rendering app")
        return (
            <>
                <StatusBar translucent style="dark"/>
                <View style={{ flex: 1, paddingTop: Constants.statusBarHeight }}>
                    <Provider store={Store}>
                        <PersistGate persistor={persistor}>
                        {/*<OneSignalSubscription />*/}
                        <NavigationContainer theme={MyTheme}>
                            <ScreensEmptyNavigator/>
                        </NavigationContainer>
                    </PersistGate>
                    </Provider>
                </View>
            </>
        );
    }
}

registerRootComponent(App)

And the code of my ScreensEmptyNavigator :

import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {EmptyScreen} from "./empty.screen";
import React from "react";

const Stack = createNativeStackNavigator();

export const ScreensEmptyNavigator = () => {

    console.log("Rendering empty navigator")
    return (
        <Stack.Navigator initialRouteName="EmptyScreen">
            <Stack.Screen name="EmptyScreen" component={EmptyScreen} />
        </Stack.Navigator>
    );
}

Any idea what is causing this slow rendering ? No API calls are made at this stage ...

The thing is this app have absolutely no documentation so I don't really know what choices have been made during the app development. Expo have been used but the app got probably ejected at one point and now the app can't be ran with expo but only with the react native CLI.

Here is the dependencies of the app in case you need them :

"dependencies": {
    "@react-native-async-storage/async-storage": "~1.16.1",
    "@react-native-community/masked-view": "^0.1.10",
    "@react-navigation/bottom-tabs": "^6.2.0",
    "@react-navigation/native": "^6.0.8",
    "@react-navigation/native-stack": "^6.5.0",
    "@react-navigation/stack": "^6.1.1",
    "@reduxjs/toolkit": "^1.7.2",
    "babel-plugin-transform-inline-environment-variables": "^0.4.3",
    "date-fns": "^2.28.0",
    "expo": "^44.0.6",
    "expo-av": "~10.2.1",
    "expo-blur": "~11.0.0",
    "expo-constants": "~13.0.1",
    "expo-image-picker": "~12.0.2",
    "expo-linear-gradient": "~11.0.3",
    "expo-location": "~14.0.2",
    "expo-media-library": "~14.0.0",
    "expo-modules-autolinking": "^0.5.5",
    "expo-permissions": "~13.1.1",
    "expo-splash-screen": "~0.14.2",
    "expo-status-bar": "~1.2.0",
    "react": "17.0.2",
    "react-dom": "^17.0.2",
    "react-native": "0.64.3",
    "react-native-animated-spinkit": "^1.4.2",
    "react-native-dotenv": "^3.1.1",
    "react-native-gesture-handler": "~2.2.0",
    "react-native-google-places-autocomplete": "^2.1.2",
    "react-native-image-header-scroll-view": "^1.0.0",
    "react-native-image-zoom-viewer": "^3.0.1",
    "react-native-logs": "^4.0.1",
    "react-native-maps": "0.30.1",
    "react-native-masked-text": "^1.13.0",
    "react-native-onesignal": "^4.3.7",
    "react-native-purchases": "^4.5.2",
    "react-native-reanimated": "2.4.1",
    "react-native-safe-area-context": "3.4.1",
    "react-native-screens": "~3.12.0",
    "react-native-snap-carousel": "^3.9.1",
    "react-native-web": "0.17.6",
    "react-redux": "^7.2.2",
    "reconnecting-websocket": "^4.4.0",
    "redux-persist": "^6.0.0",
    "remove-accents": "^0.4.2",
    "styled-components": "^5.2.1",
    "supercluster": "^7.1.4",
    "use-supercluster": "^0.4.0"
  },
  "devDependencies": {
    "@babel/core": "^7.17.5",
    "@types/react": "~17.0.39",
    "@types/react-dom": "~17.0.9",
    "@types/react-native": "~0.66.16",
    "@types/styled-components": "^5.1.23",
    "babel-jest": "~27.5.1",
    "babel-plugin-module-resolver": "^4.1.0",
    "eslint": "^8.9.0",
    "eslint-config-airbnb-typescript-prettier": "^5.0.0",
    "jest": "^27.5.1",
    "log-timestamp": "^0.3.0",
    "prettier": "^2.5.1",
    "react-test-renderer": "~17.0.2",
    "typescript": "^4.5.5",
    "yarn-audit-fix": "^9.1.2"
  }

Thanks in advance :)

CodePudding user response:

From the documentation. PersistGate behaves in the following way:

PersistGate delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux.

The delay you're enduring is most probably down to this. You can try and remove PersistGate to verify this.

  • Related