-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Low performance in React Native with Redux #443
Comments
Your I think you could simplify it to: function mapDispatchToProps(dispatch) {
return {
setPrice(id) {
dispatch(testActions.setPrice(id))
},
}
} Your |
Thank you for the advice but i see same delays after applying your changes. This makes me sad because i really like redux and would like to use it for further projects |
Hm, darn. If you link to a reproduction in a separate repo someone may be able to help out more. Rest assured, setting a single value in the store and re-rendering a component is definitely, definitely performant — React, React Native, or otherwise. |
Yes, i definitely should create separate simple project for testing. still hope it's a result of libraries conflict. |
@lourd If mapDispatchToProps doesn't depend on props (function.length === 1), I'm pretty sure it is only run once per component instance. @alsh76 Your mapStateToProps will cause your component to rerender every time any action is fired. You should have it be more picky about what parts of state it needs. |
@jimbolla there is the only action in my example. and button pressing causes the only dispatching and the only rendering. the issue happens because of delay between dispatching and rendering. not because of multiple rerenderings. |
@alsh76 Have you tried you demo without any middleware (including redux-logger)? |
@foiseworth I tried to remove redux-logger and all console.log from the code. It did not help - same delays. Actually it was a test page from my current project that uses redux-thunk and react-native-router-flux as well as some other libraries. i am gonna create test project with minimal dependencies and put it on github |
@lourd, @jimbolla, @foiseworth As it turned out the cause of this issue is all components from navigation chain are staying unmounted and get rerendered behind of the visible scene So it seems not a redux issue but nevertheless I would be very grateful for advices how to handle multiple unmounted components from navigation stack in the best way. I am checking in shouldComponentUpdate if current component is visible but maybe there is the better way? |
@alsh76 please test your example with the last |
@max-mykhailenko as i figured out my performance issues were caused by navigation system. For example if the user makes any changes and dispatch them in Scene C all mounted components A, B, C are receiving props and getting rendered in same order A => B => C. If components A and B are big enough (e.g. big ScrollView list) it causes visible delays between Scene C actions and Scene C rendering as in my example a workaround for this - do not allow rendering of not visible components in shouldComponentUpdate. it resolved my performance issue i hope it will help you |
@alsh76 Thanks for response. I use NavigatorExperimental and also saw lags, but with |
@max-mykhailenko i am using with also it's important to detect end of navigation (transition between scenes). No rendering should be allowed in transition time. When navigator animation and rendering happen simultaneously it causes freezes and delays in my app. No event is fired at the end of transition. I am using if you are using and common rule i came to - the less renderings the better. |
@alsh76 How did you did you check if components were visible? |
@aljux, I use NativationExperimental but I imagine the flux one is similar in the sense that a list of routes will be maintained with an index to indicate "where we are". You can easily calculate the "distance" between the index and the requested route @alsh76 I have had a lot of problems with performance on NativationExperimental. Aside from the trick abovem, another trick that made a HUGE ( ;-) ) difference is the following: render(){
in the navigationStart and End methods I set a state boolean 'navigating'. When it's true, I force the sceneComponent to not re-render through shouldComponentUpdate. Another issue you may or may not have is that there are many more render cycles than people often realize. If you don't have a system to "guard" against fetch requests being unnecessarily re-executed with every render cycle, you will also see a big negative performance impact and even recursive loops. |
@aljux just watched for navigation events and keep full navigation history and a key of visible scene. code for
maybe in recent versions you can get foreground scene directly. should check that |
@mschipperheyn yes, thank you for pointing out. I forgot to mention about blocking re-rendering during scene-to-scene transition. If not using |
@alsh76, @mschipperheyn Thanks. |
Ok yeah navigation experimental does have that property. Don't know about the one u are using. I understood that fb wants to release some. Kind out of out of the box based on navigation experimental. Don't know ur time frame |
@aljux You can track user actions (navigation buttons and hardware back button presses). To detect end of scene-to-scene transition use InteractionManager.runAfterInteractions Have you tried onDidFocus and onWillFocus ? As far as I understand these callbacks allow to detect end and start of navigator transitions. Maybe their arguments refer to top component |
@mschipperheyn @alsh76 thanks for the tips and info, really appreciate it! |
Actually I have the same problem you mentioned in the begining, but it my case, thats propably not a navigator problem. I use react-native-router-flux for navigation, but when I start my app, there are no other components mounted (and in most cases I use Action type: reset, so it resets the stack and the result is, that there wont be other components mounted "in the background"). So now on, I have no idea how to solve my issue. The case is, I am using Redux for changing a show/hide state of two components (the one I tap on -> i have to change the source of an Image component - the icon of the button, and the other is a little box that has to be showed/hidden, depending on that value from state). With the help of connect I get from my mapStateToProps the needed property "show" from reducer, and my two components depending on this value. It works fine, but there is a delay (just like in the video example on the top of this topic). The render function is called with some ~ 1s delay. (if I add some console.log to the begining of my render function, it shows immediatly, but the components in return() are re-rendered just within that delay). Anyone else noticed this? Any tips how can I fix this issue? (the console.log was there just for a test, there are no more logs, nothing that should slow this) Update: If I use setState instead of Redux, it works well without the delay, but I dont know if I have another option in this case (I am controlling a component with another one - and they are not related to each other) |
For what it's worth here is what I do right now. We created a wrapper for this And used it in render scene
Then you can access the route a component has been rendered into. Store the navigation stack in a singleton Then you can use this slightly modified react-redux connect function, it will skip updates if component is rendered in another component tree then the currently displayed one It might be possible to package this but I have'nt had the time to look into it. |
Hi guys! I'm still having the same issue, anyone find a good way to fix it? |
@davidsamacoits blocking re-rendering of all currently not visible components in |
@alsh76 Thank you for your fast answer, but how do I check if a component needs to be rendered or not? |
@davidsamacoits it depends on which navigation system you are using. I have to specify my issue was 100% navigation issue. Not a react/redux issue. I was using react-native-router-flux. When a user was opening new screens/scenes one after another This issue could be resolved by tracking all navigation events. If you know which scene's component is currently visible ( If you are using another navigation system e.g. react-navigation then should think about using scene-to-scene transition callbacks to detect which scene is active and needs to be re-rendered. like onNavigationStateChange |
@alsh76 thanks for your answer mate. I'm using react-native-router-flux as well. I'm just not sure about how to check what is the current screen. Is it a props property or something? |
oh that was a bit tricky. I used old v3
Second step - override
|
@davidsamacoits If you are using v4 hopefully you can omit first step |
@alsh76 thank you very much. I'm actually using v4 and I saw we can now use Actions.currentScene so I did that :
Unfortunately, it still sounds to be a little bit laggy on a real device... :( Do you tried or know any other routing libraries that does not involve this kind issue? |
@davidsamacoits I did not try because finally got it worked fast and smooth enough if you have similar issue |
@davidsamacoits also take in attention production build will work faster than dev one. especially if you have debugger enabled |
FWIW I had this same "ghost latency" issue when in dev mode. When I did an actual ios build and deployed it to my iphone, the latency completely disappeared. Interestingly enough, this latency issue only happens on ios, not android. It must be something to do with the javascript runtime when in development. |
I have discovered some issues with performance in my react native app. It seems to be caused by react-redux bundle.
As you can see in the video
https://youtu.be/D5L-RM5EY5E
there is a significant delay between action dispatching and view rendering. On real devices it looks even worse. There are no API calls in this example. Only simple actions dispatching and state changes. On other hand Facebook Flux implementation and simple call of setState work much more faster.
Any ideas how to improve the app performance?
I am using react: v15.2.1, react-native: v0.29.2, react-redux: v4.4.5,
View
Actions
Reducer
The text was updated successfully, but these errors were encountered: