Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

react-navigation 5.0 is extremely slow. #7756

Closed
Neha0595 opened this issue Mar 8, 2020 · 66 comments
Closed

react-navigation 5.0 is extremely slow. #7756

Neha0595 opened this issue Mar 8, 2020 · 66 comments

Comments

@Neha0595
Copy link

Neha0595 commented Mar 8, 2020

I just update my existing project from react-navigation 3.0 to 5.0, I experienced a very slow transition from one screen to another, revert back to 3.0 again the transition is much fast as compared to 5.0

@github-actions
Copy link

github-actions bot commented Mar 8, 2020

Hey! Thanks for opening the issue. Can you provide a minimal repro which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible. The easiest way to provide a repro is on snack.expo.io. If it's not possible to repro it on snack.expo.io, then you can also provide the repro in a GitHub repository.

@github-actions
Copy link

github-actions bot commented Mar 8, 2020

Hey! Thanks for opening the issue. Can you provide more information about the issue? Please fill the issue template when opening the issue without deleting any section. We need all the information we can to be able to help. Make sure to at least provide - Current behaviour, Expected behaviour, A way to reproduce the issue with minimal code (link to snack.expo.io) or a repo on GitHub, and the information about your environment (such as the platform of the device, exact versions of all the packages mentioned in the template etc.).

@medelvann
Copy link

i have this problem too in debugger mode, i used TabbarBottom with icons and drawer, but when i click icons to load routes in debugger mode is slow and sometimes does not reaction to click

@DovletAmanov
Copy link

Same here, Transitions are laggy even running heavy functions in InteractionManager.runAfterInteractions(...). Btw, v4 is bit faster than v5 with same codebase

@JustynaKK
Copy link

i have this problem too in debugger mode, i used TabbarBottom with icons and drawer, but when i click icons to load routes in debugger mode is slow and sometimes does not reaction to click

Same here, with v5 it is difficult to work in debugger mode, as tab buttons not reacting on press, or reacting after long time. Without debugger turned on, everything works smooth

@andreipfeiffer
Copy link

I've recently migrated from v3 to v5 using createBottomTabNavigator with custom SVG icons inside a Stack, but I don't see any lag on an iOS Simulator.

@medelvann
Copy link

@andreipfeiffer in android and debugger mode this problem happening, I didn't test in IOS

@Neha0595
Copy link
Author

Hey! Thanks for opening the issue. Can you provide a minimal repro which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible. The easiest way to provide a repro is on snack.expo.io. If it's not possible to repro it on snack.expo.io, then you can also provide the repro in a GitHub repository.

@medelvann
Copy link

@Neha0595 why you closed this issue?

@Neha0595 Neha0595 reopened this Mar 12, 2020
@Neha0595
Copy link
Author

@medelvann By mistake I tap on close button

@yenda
Copy link

yenda commented Mar 13, 2020

Are you using a nested tab navigator? I have a noticeable delay with a nested tab navigator inside another one. The parent tab navigator navigates instantly, but the nested one takes at least half a second to navigate from one tab to another. There is something odd with the nested navigation because when I swipe between the nested tabs, it is instant, there is no delay, so the view is already rendered. I also noticed that if I move all the screens to the parent it is still instant navigation.

@kamui545
Copy link

kamui545 commented Mar 13, 2020

Thanks @yenda, I've had the same issue with a BottomTabNavigator nested inside a StackNavigator.
Moving the "BottomTabNavigator" to the root seemed to improve the navigation.

It also fixed weird delays / bugs on my UI:

  1. For example, when I pressed a button that simply add a loading icon (react-native-paper). Before the patch, the icon appeared 1s+ after the press, now it is instant. (This screen is just UI example, no API calls or anything fancy). Same issue with a button to display a snackbar.

  2. When I toggled my dark mode, it used to be slow and also reset my "BottomTabNavigation" to the home page, instead of the current (settings). Now it is faster and no reset happening.

Would it be possible that this use case of nested navigation, somehow triggers re-render of other components, causing the app to slowdown and having other side effects? (again, my app is plain UI, nothing fancy, no backend plugged yet)

On a side note, on Android devices, I still have weird issues with transition effects (tab and stack transitions)... Might be something else though.

@satya164
Copy link
Member

When I toggled my dark mode, it used to be slow and also reset my "BottomTabNavigation" to the home page

looks like you might be creating components during render.

with v5 it is difficult to work in debugger mode

debugger always has issues with touchables and timing related stuff, nothing new in v5. your code is running on chrome browser instead of the device, so it's going to run differently

@yenda
Copy link

yenda commented Mar 15, 2020

@kamui545 btw I solved my nested navigator issue, I noticed the screens were all re-rendering on tabPress, the issue for me was that the navigation-props were passed as input that triggered re-render. I am not sure it applies to you because I'm writing in clojurescript but basically all I need to fix that was passing the navigation props only on component creation and not as input of the rendering function, so that changes to the navigation props don't trigger a re-render.

I also had another bug with a custom bottom bar, where I was accidentally emiting the tabPress event outside of the tabPress function, as a consequence my nested tab navigator was re-directing to the first screen of the nested tab-navigator when I was trying to do an action that would trigger a re-render of the bottom bar

@TamerlanG
Copy link

I've tested and this problem only happens on android on debugger mode. On ios, it's working smoothly with debugger mode on.

@scarlac
Copy link

scarlac commented Mar 18, 2020

If you are using a Drawer.Navigator there seems to be a performance regression from v3 => v5. It re-renders every time a nested stack navigator changes screen, causing entire stack to re-render, which is extremely costly. I am currently investigating a workaround and debugging it but if you had any drawer navigators with nested stack navigators, keep this in mind.
My WIP workaround is using React.useMemo() inside the nested stack navigator to wrap all the screens. Not optimal but it does work.

I should note that for me, this has nothing to do with the debugger - I have it disabled and notice a significant slowdown. Had v3 and v5 running side by side in simulators and could see the difference.

@xstable
Copy link

xstable commented May 25, 2020

@scarlac Thanks for this answer.
I have an Drawer as main-navi and some stack-navigators inside. I notice, that there is a notable delay between tapping (even if tapped field will be highlighted immediately), and switching to that Screen and closing the drawer.
Do you have an example how you used React.useMemo() for wrapping all screens?

@scarlac
Copy link

scarlac commented May 25, 2020

I don't have an example that I can share. I did not find a workable solution - hence why I said WIP (Work In Progress). If you wrap the function that outputs all your <Stack.Screen/> stuff, you see an improvement in performance but you'll also break your app. It is a regression bug.

@dane-du-plessis
Copy link

Any updates on this? We are still experiencing this unacceptably slow switching.

1 similar comment
@richagain
Copy link

Any updates on this? We are still experiencing this unacceptably slow switching.

@scarlac
Copy link

scarlac commented Aug 16, 2020

@richagain Your best hope is to open a new ticket and compile as much proof as possible. If possible, provide a test case that demoes the issue so maintainers can fix it.

@richagain
Copy link

@richagain Your best hope is to open a new ticket and compile as much proof as possible. If possible, provide a test case that demoes the issue so maintainers can fix it.

after upgrading the version of react navigation, the issue was fixed.

@xstable
Copy link

xstable commented Aug 18, 2020

@richagain
after upgrading the version of react navigation, the issue was fixed.

from version... to version ?? Please provide more details to make your comment helpfull.

@MoeJw
Copy link

MoeJw commented Aug 22, 2020

@richagain still the same thing );

@ab-sami
Copy link

ab-sami commented Dec 7, 2020

Any update on this? I am also facing the same issue on Android.

@dane-du-plessis
Copy link

I think the issue is related to the number of nested tabs. Experiment by reducing the number of tabs you have. We were able to work around the issue by removing a tab. Different designs will not always allow for that.

@satya164 this is not because of the debugger, although connecting a debugger will certainly slow performance in any app. We had this issue in an app released on Firebase on a test device. No debugger was connected.

My company has moved to other cross-platform frameworks for mobile. Where performance is critical, we write native code. Heavy dependence on third-party libraries has its pros and cons.

@MrXyfir
Copy link

MrXyfir commented Dec 7, 2020

@dane-du-plessis The number of nested tabs does indeed make a difference. We were able to get the performance to an acceptable (but still not perfect) level by decreasing our tabs from 5 to 3.

@Saad9624
Copy link

Saad9624 commented Jan 9, 2021

the problem comes in when you switch between nested tabs this is major issue and should be solved uptill now

@HoangNgocThang
Copy link

android not press bottm tab navigation when debug . can i h y?
react navigation v5
react native 0.63.4
in my app.js
import 'react-native-gesture-handler';
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { StyleSheet, Image, View, Alert } from 'react-native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './src/screens/HomeScreen';
import AccountScreen from './src/screens/AccountScreen';
import HealthRecordsScreen from './src/screens/HealthRecordsScreen';
import Colors from './src/assets/colors';
import LoginScreen from './src/screens/LoginScreen';
import RegisterScreen from './src/screens/ResgiterScreen';
import InputPhoneOrEmail from './src/screens/InputPhoneOrEmail';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './src/redux/reducers';
import AppLoadingContainer from './src/components/AppLoading';
import OtpScreen from './src/screens/OtpScreen';

const tabIconHome = require('./src/assets/images/BottomTab/tabIconHome.png');
const tabIconUser = require('./src/assets/images/BottomTab/tabIconUser.png');
const tabIconRe = require('./src/assets/images/BottomTab/files.png');

const Stack = createStackNavigator();
const Auth = createStackNavigator();
const Home = createStackNavigator();
const Account = createStackNavigator();
const HealthRecord = createStackNavigator();
const Tab = createBottomTabNavigator();

function HomesStack() {
return (
<Home.Navigator>
<Home.Screen
options={{ headerShown: false }}
name="HomeScreen"
component={HomeScreen}
/>
</Home.Navigator>
);
}

function HealthRecordsStack() {
return (
<HealthRecord.Navigator>
<HealthRecord.Screen
options={{ headerShown: false }}
name="HealthRecordsScreen"
component={HealthRecordsScreen}
/>
</HealthRecord.Navigator>
)
}

function AccountsStack() {
return (
<Account.Navigator>
<Account.Screen
options={{ headerShown: false }}
name="AccountScreen"
component={AccountScreen} />
</Account.Navigator>
)
}

function BottomTabNavigation() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
if (route.name === 'Trang chủ') {
return <Image source={tabIconHome} resizeMode='contain' style={[styles.icon, { tintColor: focused ? Colors.main : 'grey' }]} />;
}
if (route.name === 'Tài khoản') {
return <Image source={tabIconUser} resizeMode='contain' style={[styles.icon, { tintColor: focused ? Colors.main : 'grey' }]} />;
}
if (route.name === 'Hồ sơ') {
return <Image source={tabIconRe} resizeMode='contain' style={[styles.icon, { tintColor: focused ? Colors.main : 'grey' }]} />;
}
},
})}
tabBarOptions={{
activeTintColor: Colors.main,
inactiveTintColor: 'gray',
labelStyle: {
fontSize: 14
}
}}
>
<Tab.Screen
name="Trang chủ"
component={HomesStack}
// listeners={({ navigation, route }) => ({
// tabPress: e => {
// Alert.alert('a')
// }
// })}
/>
<Tab.Screen
name="Hồ sơ"
component={HealthRecordsStack}
/>
<Tab.Screen
name="Tài khoản"
component={AccountsStack}
/>
</Tab.Navigator>
)
}

function AuthsStack() {
return (
<Auth.Navigator>
<Auth.Screen
options={{ headerShown: false }}
name="LoginScreen"
component={LoginScreen}
/>
<Auth.Screen
options={{ headerShown: false }}
name="RegisterScreen"
component={RegisterScreen}
/>
<Auth.Screen
options={{ headerShown: false }}
name="InputPhoneOrEmail"
component={InputPhoneOrEmail}
/>
<Auth.Screen
options={{ headerShown: false }}
name="OtpScreen"
component={OtpScreen}
/>
</Auth.Navigator>
)
}

const store = createStore(reducer)

const App = () => {
return (

<View style={{ flex: 1 }}>

<Stack.Navigator>

        <Stack.Screen
          options={{ headerShown: false }}
          name="AppLoading"
          component={AppLoadingContainer} />

        <Stack.Screen
          options={{ headerShown: false }}
          name="Home"
          component={BottomTabNavigation} />

        <Stack.Screen
          options={{ headerShown: false }}
          name="LoginScreen"
          component={LoginScreen}
        />

        <Stack.Screen
          options={{ headerShown: false }}
          name="RegisterScreen"
          component={RegisterScreen}
        />

        <Stack.Screen
          options={{ headerShown: false }}
          name="InputPhoneOrEmail"
          component={InputPhoneOrEmail}
        />

        <Stack.Screen
          options={{ headerShown: false }}
          name="OtpScreen"
          component={OtpScreen}
        />

      </Stack.Navigator>
    </NavigationContainer>
  </View>
</Provider>

);
};

const styles = StyleSheet.create({
icon: {
height: 22, width: 22
}
})

export default App;

@JimVanEeden
Copy link

JimVanEeden commented Mar 30, 2021

I have the same problem, switching back to v3 fixes the issue for me, but this is obviously not ideal. I even tried v6, also too slow. Especially the bottom tabs are an issue.

Edit: I also tried v4, same slowness issue.

@NguyenDuyThang
Copy link

Any updates on this issue ? I am still facing this problem and tried all solutions above, they didn't help. Switching back to v3 is so painful for me :(.

@HoangNgocThang
Copy link

Hi NguyenDuyThang. Bạn nên dùng trinh debug mới nhé thì sẽ giải quyết vấn đề trên flipper. k dubug với chomre nữa

@MrAdex77
Copy link

MrAdex77 commented Jun 4, 2021

Hello i have same problem, and i tried many solutions but its still loading so slow when i do push on navigator

@artvichi
Copy link

It can't render even 10 simple components without delays..

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

1 similar comment
@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@NguyenDuyThang
Copy link

I have figured out the problem.

It turned out the redux is the problem. In my case, when I use the connect method of redux in class component style, it somehow takes time to connect the component to redux store before we navigate. The bigger your redux is, the more time it takes.

I solve it by applying hooks (functional component) instead of class component so that I no longer use the connect method anymore.

@github-actions
Copy link

github-actions bot commented Sep 1, 2021

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@vbylen
Copy link

vbylen commented Jan 20, 2022

I have two nested navigators in my bottomtabs navigator and it completely killed the app performance.

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@dotku
Copy link

dotku commented Feb 16, 2022

I have a simple project here: https://github.com/dotku/dk-i18n-trading-calculator feel that switching between screen, the transition is still slow; might take 1 sec to switch between different screen. Any performance tune up hint? or performance tracking tool to help the issue?

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@aximut
Copy link

aximut commented Apr 9, 2022

Strange that nobody seems to care about this issue. This inevitably pops up if you really try to make use of React how it is supposed to be used. Deep nesting and careful design of the mutual relationships and props passing.

After spending dozens of hours on this particular bug, I came up with a solution that fixed 99% of our performance issues. I think that the solution in general should be implemented upstream (i. e. in this plugin) and that it is not something to bother the downstream developers with.

So basically we had a lot of these, nested

<Tab.Screen
  children={props => (
    <Other>
      <More/>
      <EvenMore ref={...} otherprop={...} />
    </Other>
  )}
/>

Instead, what you should do according to the official solution is concatenating all children into an extra component

<Tab.Screen
  children={props => (
    <Child {...props} ref={...} otherprop={...} />
  )}
/>

and then

<Tab.Screen
  component={Child}
/>

However, that way you can't pass any custom props. So instead, what you really should do is

<Tab.Screen
  children={props => (
    <MemoizedChild {...props} ref={...} otherprop={...} />
  )}
/>

and then outside (!) of any (functional, class) component, at the top of the .jsx, .tsx file, define

const MemoizedChild = React.memo(Child);

Going with this pattern over the entire app frontend resulted in a HUGE speedup.

@github-actions
Copy link

github-actions bot commented Apr 9, 2022

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@raajnadar
Copy link
Member

@aximut No one can help you if you do things in the wrong way and do not provide a quick runnable repro (You can see someone gave the repro recently).

  1. You need to pass the screen into component props. All the examples in the docs are in this format, now the question is how to pass some props, why not send the props as params while navigating? or use global state management.

  2. Use render props to render a screen instead of passing component props. Like it is done in the example app in the same repo.

https://github.com/react-navigation/react-navigation/blob/main/example/src/index.tsx#L322-L329

@github-actions
Copy link

github-actions bot commented Apr 9, 2022

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@satya164
Copy link
Member

satya164 commented Apr 9, 2022

@aximut the performance concerns about what you are doing are clearly documented. I recommend reading the documentation first to avoid wasting time.

https://reactnavigation.org/docs/hello-react-navigation#passing-additional-props

@github-actions
Copy link

github-actions bot commented Apr 9, 2022

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@salmanR107
Copy link

Still an issue. Facing slow navigation on Android.

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@react-navigation react-navigation locked and limited conversation to collaborators Apr 12, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests