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

Stacknavigator transition extremely slow #608

Closed
natashache opened this issue Mar 8, 2017 · 105 comments
Closed

Stacknavigator transition extremely slow #608

natashache opened this issue Mar 8, 2017 · 105 comments

Comments

@natashache
Copy link

natashache commented Mar 8, 2017

Hi,

I use nested navigator structure and have noticed that the transition between some screens are very, very slow.

Here's the setup:

export const MainNavigator = TabNavigator({
  Search: { screen: Search},
  Explore: { screen: Explore },
  CourseNavigator: { screen: CourseNavigator },
  MyProfile: { screen: MyProfile }
}, {
  initialRouteName: 'CourseNavigator',
  navigationOptions: {
    tabBar: {
      visible: false
    },
    header: {
      visible: false
    }
  },
})

export const CourseNavigator = StackNavigator({
    MyCourses: { screen: MyCourses },
    PlayerNavigator: { screen: PlayerNavigator }
  }, {
  headerMode: 'screen'
})

export const PlayerNavigator = StackNavigator({
    CoursePage: { screen: CoursePage },
    Player: { screen: Player }
  }, {
    headerMode: 'screen',
    mode: 'modal'
})

So PlayerNavigator is nested under CourseNavigator, which is under MainNavigator.

What's moving very slow is the transition between the Mycourses screen in CourseNavigator and the CoursePage screen in PlayerNavigator. It takes two full seconds for the screen to change.

The code for the transitioning is very straightforward:

  goToCourse(course) {
    const {navigate} = this.props.navigation
    navigate('PlayerNavigator')
    this.props.setCurrentCourse(course)
  }

// And then in the render function...

        <Button transparent small
          onPress={ () => this.goToCourse(course) }>
          <Icon name='ios-arrow-forward' />
        </Button>

Wondering if anybody has experienced similar slowness and what could be the potential cause?

@chandu0101
Copy link

Wondering if anybody has experienced similar slowness

I am also facing similar issue now (iOS Simulator) , it used to be fast :s

@GertjanReynaert
Copy link

Without reading to much into the issue, you might want to check debug > slow animations in your ios simulator. cmd+t activates it, and so you could have triggered it by accident when you meant to create a new tab in a browser for example.

@natashache
Copy link
Author

@GertjanReynaert Thanks. Unfortunately this is not the issue. Slow animations is turned off. And I'm experiencing the same slowness on both ios simulator and iphone. In general, I've found the transition of stackNavigator to be slower than tabNavigator. But this particular transition mentioned above is slow to the extreme. If I don't find a solution, I'll just have to abandon this library all together, because this creates terrible user experience.

@jurassix
Copy link

jurassix commented Mar 14, 2017

@natashache - I'm having similar performance issues and am able to workaround them by disabling Remote JS Debugging. I'm not seeing the issue with Hot or Live Reloading turned on.

Hope that helps.

@natashache
Copy link
Author

@jurassix thanks for the suggestion. Unfortunately this is not related to remote debugging. The slowness is present no matter whether I use remote debug or not.

@sercanov
Copy link

sercanov commented Apr 1, 2017

Having the same, TabNavigator is fast as flash but StackNavigator like kind a have delay before pushing screens. Same on pressing the Back button, but have no issues when swiping back.

Behaving like doing a lot of calculations on JS thread, perf monitor also show tremendous FPS drop when pushing screens.

  • tested on iOS only
  • RN - 0.42.3
  • RNav - beta7
  • using with redux

@nico1510
Copy link

nico1510 commented Apr 1, 2017

#706 may be related

@sercanov
Copy link

sercanov commented Apr 4, 2017

I dont think it's related @nico1510

I have performance problems on simulator too, here are some key points;

  • Have 3 StackNavigators nested in TabNavigator with 3 tabs.
  • Have a redux action call in one of StackNavigator route's componentWillUnmount that resets the component to initialState.
  • If I comment out this line it seems to fast a bit. But the reset action is very light, don't think it has impact, doing fine with NavigationExperimental
  • I think componentWillUnmount doesn't fire immediately and if I navigate to another screen before it fires, the StackNavigation becomes completely unresponsive. Logs shows that it fires the navigate action but doesn't mount the component so touch responders are not responding.
  • TabNavigator still works when these freezes happen.

I'll try to make an isolated project to show this.

@cbrevik
Copy link

cbrevik commented Apr 10, 2017

I agree that it navigates very slow.

Even with a simple setup that only includes one or two views, that navigates to each other or to themselves. Even with something as simple as the one in this test app: https://github.com/cbrevik/react-navigation-test

@vishim
Copy link

vishim commented Apr 14, 2017

The Tab bar and the header are horribly slow to update on Android. Slow, even on a real device with a release build 😞

I have a Stack -> Tab -> Stack nesting and using Icons from native-base

ios is better

Any help would be appreciated !

@vinhtq
Copy link

vinhtq commented Apr 20, 2017

On Android it even renders page twice

@joncursi
Copy link

I'm getting the same slowness on Android. iOS is decently fast, but Android takes has 2+ second delays

@edo1493
Copy link

edo1493 commented May 13, 2017

I have a particularly slow transition on a single screen (iOS), which is rendering a chart with svg (but this is on the js thread, so why would be a problem?).

@andfs
Copy link

andfs commented May 15, 2017

I'm facing the same problem on a real android device...

@arnaubennassar
Copy link

Same here, in Android device. The crazy thing is that when I have Remote JS Debugging enabled it goes way faster!

@haaswill
Copy link

Same here, on iphone 7, without Debug Remote JS and when I press a button, on 'headerRight' to navigate to another screen, twice it open the next screen two times and stack them. So when I get back once, it gets back to the page it should have been all along.

@arnaubennassar
Copy link

@haaswill you are facing to different problems.
The double/multiple tap on the button can be fixed by adding a custom navigationHelpers such as the one by @microwavesafe in #271
The bad performance without Debug JS Remote, in my own experience is due to the use of console.log, but could be different in your case.

@andfs
Copy link

andfs commented Jun 2, 2017

@arnaubennassar I don't have any console.log. I'm waiting new versions to see if the problem is solved :/

@deathemperor
Copy link

deathemperor commented Jun 6, 2017

I'm having the delay even in RELEASE build of Android. Device is Samsung Galaxy S7 Edge.

demo: https://im2.ezgif.com/tmp/ezgif-2-9ec91aa14b.gif

notice that when it's delayed, no animation was played

@DavoCg
Copy link

DavoCg commented Jun 8, 2017

Same here, in the iOS simulator everything is super fast without any delay (with or without remote JS debugging enabled) but when I run it on my iPhone 6s there is at least 500ms delay before navigation push.

@sercanov
Copy link

sercanov commented Jun 8, 2017

I gave it another shot after a month, with 1.0.0-beta.9 i have no issues right now. Using 3 different routers with tab - stack nested navigations and its performing very well

@WillyRamirez
Copy link

@sercanov can you please tell me which version of React and React-native you are using? Downgrading to *.beta.9 for me alone didn't do the trick...

@sercanov
Copy link

sercanov commented Jun 9, 2017

@WillyRamirez
React 15.4.2
RN 0.42.3
react-redux 4.4.5

I dont know what but i think there is a minor bug creates the performance issues in some cases.

You could look at components lifecycle events, like doing state-heavy processes in componentWillMount or in scene transitions.
Also check your navigation reducers and immutable conversions.

@WillyRamirez
Copy link

WillyRamirez commented Jun 10, 2017

@sercanov I went back to version 0.43.0 since im using flatlists i can't go back further, however, I tried removing the FlatLists and it now works on emulator, still slight delay on phone.

@meilers
Copy link

meilers commented Jun 11, 2017

I'm using version 1.0.0-beta.11 and it's terribly slow on Android. On iOS it's decently fast, but definitely not on Android.

@JimmyDaddy
Copy link

I got the same problem T_T

@philsam
Copy link

philsam commented Jun 16, 2017

If you're having problem where tapping a buttons responds slow or the screen requires a tap to transition in certain scenarios - see @jurassix comment to turn off remote debugging. it solves the problem

@JimmyDaddy
Copy link

I solve my problem by unbinding the navigation reducer from my HOME page witch contains a large list. The reason of my problem is every time I navigate it will update my HOME page then make the translation between every screens slow.

@GollyJer
Copy link

GollyJer commented Jan 4, 2018

Good tip @sapjax. Here's what mine looks like. LOGGING_ON is my own override.

// Log state changes.  https://github.com/evgenyrodionov/redux-logger
const LOGGING_ON = false;
const debuggingInBrowser = !!window.navigator.userAgent;
if (ENV === 'development' && debuggingInBrowser && LOGGING_ON) {
  const { createLogger } = require('redux-logger');
  const logger = createLogger({
    collapsed: true,
    duration: false,
    timestamp: false,
    diff: true,
  });
  middleware.push(logger);
}

Also I no longer pass anything in ScreenProps. In my experience doing so significantly slows down navigation speed.

@madcoda
Copy link

madcoda commented Jan 12, 2018

Do you have redux logger enabled in production build?
Here is a quick snippet you can use to enable logger in dev and have it off in production

import DefaultReduxLogger from 'redux-logger';

const MIDDLEWARES = [
    thunkMiddleware,
     __DEV__ && DefaultReduxLogger,
     __DEV__ && perfLogMiddleware,
].filter(Boolean);
const mainMiddleware = applyMiddleware(... MIDDLEWARES);

@myfootball
Copy link

myfootball commented Jan 25, 2018

When removing all logging and still have performance issues, check your mapStateToProps functions in your containers. Most certainly you return every time it gets called some kind of new object.

@kadusjc
Copy link

kadusjc commented Jan 26, 2018

I've changed from Stack to TabNavigator
I had to set visible false in all tabs and disable swipe either

StackNavigator is really slow while Tab Navigator is really fast

I hope its usefully

@typehorror
Copy link

After setting the duration to 0 in the transitionConfig the lag went away :

const AppScreens = TabNavigator(
    Home: {
      screen: Home,
    },
    Profile: {
      screen: Profile,
    },
  },
  {
    initialRouteName: "Home",
    swipeEnabled: false,
    animationEnabled: false,
    lazy: true,
    transitionConfig: () => ({
      transitionSpec: {
        duration: 0,
      },
    }),
  },
);

@kadusjc
Copy link

kadusjc commented Jan 29, 2018

but you are using TabNavigator, there is no lag in TabNavigator. The problem occurs when using StackNavigator

@sm2017
Copy link

sm2017 commented Feb 1, 2018

Why stack navigator is too fast (at 60fps) in iOS device (and simulator) but drop frames and slow (2 seconds delay) on android? What must I do for android performance?

@shashankwadi
Copy link

shashankwadi commented Feb 7, 2018

Try following 5 things -:
1> Add activeOpacity with value 1 because if you set alpha JS thread send this too main UI thread and hence the delay.
Ex ->

Title of Button

2> Add your component will mount code inside Interaction manager It will run your JS code after the transition will complete
Ex ->InteractionManager.runAfterInteractions(() => {
});

3>set lazy to true for tab bar, it will help in not reloading unwanted controllers/components
Ex ->
const tabNavigatorConfig = {
tabBarPosition: 'bottom',
tabBarOptions: {
},
mode: 'card',
lazy:true,
}

4> Remove all logs, and comment logger middleware if u r using.
5> Run in release mode.

@brentvatne
Copy link
Member

brentvatne commented Feb 7, 2018

if someone can provide me with an app that reproduces this problem, that would be helpful. otherwise we can't do much. it's quite possibly related to logging, as mentioned above. another possibility is lots of large images. I need an app where this is happening to help.

@dantman
Copy link

dantman commented Feb 7, 2018

Logging is likely not the sole cause. We already know that Stack Navigator's implementation is problematic, every navigation change (even a setParams for a single screen) triggers the render() of every single route, even though all but 1-2 of them are invisible, irrelevant, and don't actually care about the change to navigation data.

That adds up, even if you aren't using heavy components the render() of a screen component is typically not negligible because it's responsible for defining all the views for the layout of a screen. And that will inevitably add up when you have a bunch of routes in the stack. PureComponent doesn't get around this because navigation changes each time the state changes. You'd need a very specific shouldComponentUpdate to ignore irrelevant data when not the active screen, which shouldn't be necessary.

Fixing this (finding a non-hacky way to not re-render screens unless they are active, were active in the previous state, or had their params changed) will likely be the thing that solves this bug for most people.

@brentvatne
Copy link
Member

brentvatne commented Feb 8, 2018

every navigation change (even a setParams for a single screen) triggers the render() of every single route

I am new to working on this project, can you elaborate on this @dantman? I added console.log to render methods on the Simple Stack example and only one log fired any time I pushed a new screen. How can I repro this?

@dantman
Copy link

dantman commented Feb 8, 2018

@brentvatne It's been awhile, I'll have to try an examine the current behaviour myself.

@andfs
Copy link

andfs commented Feb 8, 2018

@brentvatne I'll send you as invitation to a repo in bitbucket. A very basic code that uses react-navigation with extremely slow transitions in an android release or without debug mode

@brentvatne
Copy link
Member

brentvatne commented Feb 8, 2018

@andfs - the project that you invited me to, "trending", doesn't have react-navigation installed in it, it just has a google sign in screen

@andfs
Copy link

andfs commented Feb 9, 2018

@brentvatne sorry, the right code is in develop branch

@brentvatne
Copy link
Member

@andfs - you're using 1.0.0-beta.9 and react-native 0.43 here.. these are both very old (about 1 year). please update to the latest version before reporting bugs. additionally, the app doesn't compile

@andfs
Copy link

andfs commented Feb 9, 2018

@brentvatne this bug report was opened about a year ago and until now there are interactions in this issue, so there are people facing this problem yet. You asked for an example of project with this problem and that was the only one that I have.
Tomorrow I'll update. If there is no problem I'll share it with evrybory to use as example ;)

@samdoj
Copy link

samdoj commented Feb 11, 2018

I wanted to make an update. I was using a package called react-native-simple-markdown which makes a new for every word which caused it to use a lot of memory. The problem resolved when I switched to react-native-markdown-view. My point here is not about specific libraries, but rather about memory. It seems that react-navigation has trouble transitioning to and from scenes that have deeply nested components like this. I'm thinking it has something to do with measurements. Bottom line: Make sure you and your packages are using memory efficiently for best responsiveness.

@esco
Copy link

esco commented Feb 19, 2018

I had similar issues that ended up being caused by a delay in TouchableOpacity used for the nav buttons. Switching to TouchableHighlight made it instant.

@sm2017
Copy link

sm2017 commented Feb 19, 2018

@esco can you share more details

@farid-ouachrar
Copy link

farid-ouachrar commented Feb 20, 2018

I also had a similar issue and it was causing the navigation as a whole to be very slow over time. After many things done, the thing i found was causing this issue is that i left redux logger logging, as soon as i deleted the logging everything worked seamlessly.
the issue is in the picture below.
image

@sm2017
Copy link

sm2017 commented Feb 22, 2018

How can I disable transition for stack navigator?

@GastonSchWun
Copy link

@sm2017 Check this #1254

@brentvatne
Copy link
Member

i'm going to close this issue because we need a project that can reproduce this without a bunch of superfluous code. sorry. please create a new issue with a minimal example project that reproduces your problem if you would like us to investigate further into your specific problem. we are constantly doing things to improve performance and there's not much use in keeping an issue like this open which points to no clearly defined and demonstrable problem.

@react-navigation react-navigation locked and limited conversation to collaborators Feb 23, 2018
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