Tips for improving performance of React Native apps

While researching a performance issue in a React Native app by doing a deep dive into the bridge, I stumbled upon this nice list of tips by jamsch.

The list – which touches react-navigation, the types of lists one can use, etc. – was originally posted as a comment on a Github Issue, but deserves way more attention, as it’s great for developers new to RN, who haven’t had to learn this stuff the hard way (yet).

  1. Try to use React Native’s FlatList/SectionList/VirtualizedList where you can and not array.map() as it allows for asynchronous rendering of components in your viewport which is important for mobile devices.
  2. With the nature of React, any component that has updates to it’s state/props will re-render all of it’s child components, and likely the children of those components as well. It’s up to you to make sure that your components should update or not by using shouldComponentUpdate or changing the components to a PureComponent. There’s often times where you don’t even know that components are re-rendering when they shouldn’t be. Start by checking the app root component and going down from there.
  3. React Navigation will typically have any screen you have in your navigation state rendered. State-heavy screens may suffer in performance especially when there’s background state updates. It’s also easy to add more routes to your navigation state and more difficult to take them off.
  4. Make sure that the screen you’re trying to navigate to isn’t heavy on it’s initial render. Your components should preferably be light on the first render and accumulate with data later from interaction and server responses. react-navigation will only transition to the screen once it’s typically fully rendered. One thing that could help is configuring initialNumToRender on your FlatList/SectionList component. Otherwise this may take seconds to render new screens using react-navigation.
  5. The renderItem function should render stateless list item components. If it needs state context (e.g. whether the list item is expanded or selected), it should be using the parent’s state as seen in the documentation.
  6. Unusual things may start happening if you render more than one FlatList/SectionList/VirtualizedList in one component (e.g. rendering only the current render batch and no more).
  7. Avoid wrapping your FlatList inside a ScrollView, as it will render all child components. FlatLists implement on top of ScrollViews so you can use most ScrollView props on FlatLists.
  8. Develop Android-first. iOS performance is guaranteed and you will notice performance issues sooner before having to rebuild much of your code base. React-Native was built first with iOS-only support.
  9. Using remote debugging will execute JavaScript on the host computer and not on the phone, and instead use the RN bridge to send native calls to the phone. This will likely be very slow in some situations and very fast in others. Try building the app with the release variant — react-native run android --variant=release so you can get a more accurate feel of the app’s performance.
  10. Remove any console.log() statements from your app when releasing it to production with babel-plugin-transform-remove-console.
  11. Generally as a guideline, the less JavaScript and more native code, the better performance you’ll get. React Native allows us to build user interfaces with great productivity and a shared code base but there may be times that you’ll need to go native on both platforms to get better performance.

react-navigation is a not very performant library especially for Android. It solely uses React Native’s library as a basis for all it’s navigation logic which means any additional screens/views are all loaded on to the one activity/viewcontroller which gives ‘native-like’ navigation but not true navigation. If you went to inspect the app on iOS while the app was running you’d see that the screens in your navigation state are essentially rendered and layered on top of each other. react-native-navigation (v1) is a suitable alternative if you’d rather want to use the native navigation controllers.

/me nods along.

I’d also add: Implement getItemLayout on FlatList and the like.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.