'React navigation 5 really slow and dropping JS FPS on Expo

I am currently working on a React Native (Expo) App and I am facing some performance issues. I have not found any answer yet for my problem so I hope someone can help me.

My problem is that whenever I launch the app on my physical device (Galaxy S9+) and navigate to different screens, I notice JS frames dropping from 60 all the way to like 10-30. I have a main drawer navigator, a bottom tab navigator and some stack navigators. I have basic View, Text, ... component so I don't think it is due to heavy components.(I am using react-navigation v5)

I also have to mention that I don't really see any lack of performance or JS FPS drops on an iOS simulator.



Solution 1:[1]

Android devices are a lot more sensitive to unoptimized JavaScript code because they typically have far worse JS performance when compared to iOS devices, so you have less headroom to write inefficient code. The same code running on iOS can feel smooth and on Android it can end up frequently dropping frames.

It's recommended to use React Devtools to understand the source of slow rendering performance in React apps, and I think this is a fine option here and something you certainly should do.

Another thing you can do is switch to createNativeStackNavigator wherever you are using createStackNavigator, and that will help push some of your performance concerns a little bit down the road. You can also learn more about this navigator in this YouTube video.

I'd personally do both of the above right now: 1) profile your React rendering performance and find where you're doing unnecessary / extra work, eliminate that. 2) switch to using createNativeStackNavigator.

Solution 2:[2]

Create your own animation

This animation will make your app more fast

 const App = () => {   
   const Stack = createStackNavigator();

   const TransitionScreen = {
    gestureDirection: 'horizontal',
    transitionSpec: {
      open: TransitionSpecs.TransitionIOSSpec,
      close: TransitionSpecs.TransitionIOSSpec,
    },
    cardStyleInterpolator: ({current, next, layouts}) => {
      return {
        cardStyle: {
          transform: [
            {
              translateX: current.progress.interpolate({
                inputRange: [0, 1],
                outputRange: [layouts.screen.width, 0],
              }),
            },
            {
              translateX: next
                ? next.progress.interpolate({
                    inputRange: [0, 1],
                    outputRange: [0, -layouts.screen.width],
                  })
                : 1,
            },
          ],
        },
        overlayStyle: {
          opacity: current.progress.interpolate({
            inputRange: [0, 1],
            outputRange: [0, 0.5],
          }),
        },
      };
    },
 

     };
    
      const CardOptions = {
        cardStyle: {backgroundColor: 'transparent'},
        ...TransitionScreen,
        headerShown: false,
        gestureEnabled: false,
      };

 return (
    <NavigationContainer theme={DarkTheme}>
      <Stack.Navigator>
        <Stack.Screen
          name="preloader"
          component={PreLoader}
          options={CardOptions}
        />
      </Stack.Navigator>
    </NavigationContainer>  
 );
 };
    
    export default App;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 brentvatne
Solution 2 JASIM TK