Debugging React Native Applications

Dotan Nahum
Aug 25, 2016 · 7 min read

When doing application development with interactivity, UI/UX and state, on a resource-limited platform, these questions often come up:

  • Debugging — how do you debug applications?
  • Inspecting — how do you inspect the UI tree?
  • Touchables — how to understand interactive surfaces?
  • Platform — how to reason about the “magical things” that happen out of sight?
  • Slowness — how to get visibility about what’s slow?
  • Layout — Specifically, about React — how to reason about React performance and efficiency?

This is an overview of what’s available to you within React Native and its ecosystem.

Debugging

  1. Cmd+Z (or shake) to bring up the dev menu.
  2. Select ‘Debug JS Remotely’.
  3. A fresh Chrome instance will pop up, which you can immediately use for setting breakpoints and stepping through your app’s Javascript code.
Image for post
Image for post
Image for post
Image for post

Remember to turn off remote debugging when done, by accessing the developer menu again (Cmd+Z).

Using console.log, or “console.log debugging” is also very common. It might seem a bit primitive, however with time console.log became a rather powerful tool for the Javascript developer, and it definitely isn’t equal to a dirty-feeling puts/print/cout/what-have-you.

Even if React Native doesn’t support the more advanced time, group, table interface, it would pop a yellowbox on warn, for example. React Native promotes a very fast feedback cycle, and using console.log rhymes better with that, rather than stop-the-world debugging and having to context switch — getting out of the editor and using a completely different toolset.

NOTE: There’s also Systrace, but given that it is quite low-level, we’ll cover in its own article.


Reactotron

Image for post
Image for post

Reactotron plugs into your Redux pipeline as a middleware and lets you inspect, fiddle and trace it with a live ncurses based interface which is really fun to use.

Inspecting

  1. Cmd+Z (or shake) to bring up dev menu.
  2. Select Inspector.
  3. Tap on ‘Inspect’.
Image for post
Image for post

You can now proceed to select a component, drill down or up the UI tree hierarchy by tapping the breadcrumbs pieces, and verify positioning, margins, padding and more. You can use this to find overlapping areas, surfaces that block event bubbling, transparent surfaces that overflow the existing viewport, and more.


Touchables

You can expose these with the inspector as well:

  1. Cmd+Z (or shake) to bring up dev menu.
  2. Select Inspector.
  3. Tap on ‘Touchables’.
Image for post
Image for post

You can then hide the inspector and continue interacting with your application while every touchable is exposed. Crushed border line, color depicts type of touchable:


Spying on the Bridge

Image for post
Image for post

There’s a lot to gain by simply looking at these communications. You could find bottlenecks (by identifying too much chatter over the wire), resource hogs (by observing very large objects passing back and forth), bugs (by finding misplaced communication, forgotten timers, and so on) and more.

React Native comes out of the box with a special SPY_MODE flag that you can turn on in its MessageQueue component; through which these kind of communications pass. However, this was not exposed to end-users, but for React Native developers. I wanted to change that with this pull request, by allowing end users to plug in their own “spies”.

I then proceeded to build a spying framework which you can use today called Snoopy.

And here’s how it looks like:

Aggregating and Charting Events with Bar
Aggregating and Charting Events with Bar
Aggregating and Charting Events with Bar
Aggregating and Charting Events with Bar

With Snoopy, you can build sophisticated bridge event pipelines using the powerful Reactive Extensions and FRP concepts that declaratively model what you want to observe and detect, instead of how you want to detect it.

Here are some ideas for things you can observe over the bridge with Snoopy:

  • Buffer events for one second, and raise an alert when the total events cross a threshold.
  • Identify huge calls by looking at the arguments for each event.
  • Keep an eye open by charting out the bridge communication volumes.

Check out the Snoopy repository for more.

Update: I published an in-depth article about using Snoopy!


Slowlog

I wanted to have this same concept for React Native applications.

With react-native-slowlog, you wire such a capability into your React components piecemeal, and get a high-level idea in real time of the slow things that happen around your app. It is not a fine-grained diagnostics tool, but rather a general watchdog that sits there and pops an alert when things are majorly slow.

You can find out more about slowlog in the react-native-slowlog repository.


JSEventLoopWatchdog

This idea is exactly what the JSEventLoopWatchdog component in React Native core does. It Detects stalls in the React Native Javascript event loop by scheduling a no-op task every X amount of time, recording the wall clock time it executed at in reality, and compares it to the expected time. If we have a stall, there will be a difference in clock times. The bigger the stall the bigger the difference.

To use JSEventLoopWatchdog, you supply a threshold time — the duration, in milliseconds, equal to the lag you’re willing to accept. When the lag is bigger, you’ll get console messages notifying you about it:

const JSEventLoopWatchdog = require('JSEventLoopWatchdog');
JSEventLoopWatchdog.install({thresholdMS: 200});

The bad news is that this is still an internal tool React Native uses since it’s not currently usable if you’re out of the react-native project space. The good news is that I’ve extracted it into react-native-slowlog and adapted the internals so that it can run outside of the react-native core.

To use JSEventLoopWatchdog on your own, you need to use the watchdog component of slowlog:

import watchdog from 'react-native-slowlog/watchdog'
watchdog.install({thresholdMS: 50})

Now, if anything is stalled for more than 50ms, you’ll get a notification in your logs.


React Perf Tools

React Perf Tools


Summary

I also feel I’ve had a very welcoming hand introducing my MessageQueue patch into React Native core, along with help to conform to Facebook’s standards; with such a large, high traffic project, this is not to be taken for granted.

I wish to thank Pieter De Baets, Martin Konicek and the React Native core team for doing such a great work with the community!

React Native Academy

A publication about React Native and the emerging new world…

Dotan Nahum

Written by

@jondot | Founder @ Stealth. ex-CTO at HiredScore. ex-CTO at Como. Hacker. Fullstacker. Open sourcer.

React Native Academy

A publication about React Native and the emerging new world of cross-platform mobile development.

Dotan Nahum

Written by

@jondot | Founder @ Stealth. ex-CTO at HiredScore. ex-CTO at Como. Hacker. Fullstacker. Open sourcer.

React Native Academy

A publication about React Native and the emerging new world of cross-platform mobile development.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store