Over the past six months at WeDo, we have been working on improving the performance our React Native app. With any performance issues, profiling is the first step. In this article I will cover what tools worked for us and how we utilized them to build our baseline for future performance improvements.

React Native Slowlog

React Native Slowlog has been our go to when it comes to view rendering performance. What we specifically liked about this library is the able to set a custom threshold.

It couldn’t be easier to use. Just add a single line of code in your views constructor and you will be off to profiling.

slowlog(this, /.*/)

Tracking Unnecessary Renders

This might easily be the biggest issue we faced for most of our react native performance issues. When you have a view unnecessarily rendering it slows everything down. Since we use React Redux within our app we were able to take advantage of a feature on the connection options. When setting the renderCountProp property, React Redux will pass a render count to your view. You can then either log this, display it in your view, or like we did and use React Native Debugger and inspect our components directly.

connect(stateToProps, dispatchToProps, null,

{renderCountProp: 'renderCounter'})(MyComponent)

This will give you insight into how many times your view is rendering. Can be the first red flag for tracking down unnecessary renders.

Tracking State and Prop Changes

When trying to narrow down what is causing the unnecessary renders above your first line of defense is to monitor your state and prop changes. What we ended up doing was simply just logging a lodash difference comparison on our previous and next state and prop objects in componentWillUpdate. This gave us enough insight into what was changing and what wasn’t.

componentWillUpdate(nextProps, nextState){

console.log(difference(this.props, nextProps));

console.log(difference(this.state, nextState));

}

Do take note that difference({},{}) will return an empty array. When React looks at that though {} !== {} thus a re-render. In our case we use Reselect as much as we can, so for us this wasn’t an issue as new objects are never returned unless the data within them has changed.

Redux Level Performance

Most of our performance issues were not on the Redux layer of our app. It was still worth double checking. To do this we used redux-log-slow-reduces. It isn't the perfect solution (and no longer maintained) but for us it was enough to verify that our reducers were not causing performance issues.

Track your results

Don’t make the silly mistake that we did in the beginning and not track your results. We used a lot of these tools listed above to pinpoint our problematic components and views but at the end of the day we were not tracking any of the results. So when it came time to look back and see if our efforts have paid off it was really just up to feel. “Does the app feel faster, more responsive to you” isn't a great way to track performance. Recently tracking components and views performance within a shared spreadsheet helps us track performance for better or worse.