Choosing Your React Native Debugger Environment
Recently, I had the chance to interview for a React Native development position at Microsoft. It was a fantastic sounding position — one of the interviewers threw me for a loop.
What do you think of the React Native debugger, they asked?
Me ….
Yeah. I blanked. Entirely.
Looking back, it wasn’t my finest fifteen minutes for something so basic. I’m sure they expected something like Oh, I love Visual Studio Code, it’s awesome at single step, etc. Or maybe, you know, the layout inspector could be better. I blanked. Just everything… gone. I mean, there’s like 5000 ways to debug React Native, and I couldn’t figure a single one. Not even the ones I’d been using for a while.
Needless to say, I did not get the job, but I did get a fantastic new interview question for when I interview others. (Side Note — the interviewer was pretty chill about it and just moved on. Very appreciative of their professionalism.)
So, like any good engineer, I tried to figure out why I blanked.
Google returned about 500 different results for debugging React Native. In varying stages of development. Most of them were just lists of tools. With very few examples of why you would use one over the other.
Most of them were some front end to the Chrome Inspector, which I find… okay.
Lastly — most of these results were just lists. No comparison of features, or explanations of why you would use one over the other. Just — here’s how you can debug React Native.
So, let’s talk about my needs, and then talk about the options.
- I need a cross-platform debugger. I don’t want to debug one way on one platform, and another on a different platform. I intend to release for Windows, OS X, Android, and iOS.
- I would love to have single-step debugging of my code.
- I would prefer to edit my code in the same window that I debug. (Ie — an integrated environment.)
- Layout debugging would be a boon. I am dealing with a GUI…
- Console log for those printf times…
- Something easy to setup — no need for every time to run 15 different commands to get stuff going.
- Works the same with emulated devices and real devices.
- Bonus points for being able to control runs of the code, so I don’t have to start another session, navigate to another tool, etc when trying to start up a run of the code. By run, I mean a particular emulator or device configuration, which I can also use for an automated testing config.
In short, I want to be efficient. Development is an iterative process. The faster I can clear hurdles and integrate tools to reduce friction (otherwise known as time between attempts to solve problems), the faster I will get my projects done.
React-native also adds a few more considerations to our debugging wishlist. There are multiple parts to a React-native program:
- Native module OS Specific code — these are the underlying native modules that provide the ‘native’ part of the React-native. React-native talks to these over a bridge from the Javascript layer. These are written in the language mandated by the device owner — anything from Swift, Win32, Java, or Kotlin.
- Component Layout — this is how your screen is laid out, and it is very helpful to be able to inspect each element to see where the component is on the screen, and what events or properties each component has. This is the GUI part of things, provided by the FlexView structure. Each component has properties associated with it, as well as event handlers and styles.
- State — the React-native layer, whether through Redux, or Hooks, or States, has a bunch of additional layers that can hold the results of APIs, stored state for components, etc. These need to be addressed by a debugger. State also has performance characteristics, as this can be the network portion of your calls.
- React-native Javascript code — the code in your React-native modules that runs — but that is not attached to a component. Business logic, app logic, it goes by other names as well. This generally does things like parsing input, providing magic sauce, setting up components, making components disappear, handling components, etc.
Let’s start with the Grand-daddy, the react native documentation. This documentation is actually pretty good, and contains a lot of resources. I highly recommend reading it.
https://reactnative.dev/docs/debugging lists several methods to get started. Let’s go through them one by one.
Chrome or Safari Developer Tools
This is the standard built in tool that ships with Chrome or Safari. It certainly fills some of our wish list.
The first thing you need to realize with this method of debugging is that the Javascript engine for executing React-native code moves to the browser itself — V8 in the case of Chrome. This is a downside, as the engine is different than the environment that your app runs in — usually Hermes or JavaScriptCore. Timings and execution can be different.
The second downside is kind of personal — I find the Chrome Inspector to look like trash. It’s just kind of disgusting.
There is good news though — Chrome Inspector can be extended using plugins — for instance, there already exists one for React. But the bad news is that there’s none available for React-native — and probably won’t ever be one, because of the fact that it would only have access to the V8 engine, not the entire device.
So, with that aside, let’s see:
- Cross-platform
- Does allow for console logs to show.
- Provides single-step debugging, pause on exception, watchpoints, call stacks.
- Can be made to show network and XHR timings.
- Does not have any state or redux or layout debugging ability.
- You could edit your code in place… but I don’t know why you’d want to. Then again, I know people that use dip switches and magnets to program computers just to say they can. Go figure.
All in all, this is a pretty basic debugger for the Javascript engine, although with the other tools it offers, it might be useable for some things. The fact that it is the same on all platforms is definitely a win — sort of least common denominator.
The biggest downside for me though — unless I ran it in standalone web app mode, I kept losing the Inspector in my other Chrome windows, which made debugging difficult, as well as caused strange lag issues, like onLongPress not firing at all.
This is where I started with standalone apps. It seemed interesting enough, and was standalone, so it wouldn’t get lost in my Chrome windows.
Whoops. That was a mistake. You want to debug Javascript? Look somewhere else. This was clearly not designed for that purpose.
React Developer tools is designed to be a component inspector. That is, it allows you to see each component in your React Tree, its properties, and its children. That includes the Javascript source file. You can then trace this back with your editor or another debugger.
It has the nice benefit of interacting with the Inspector on your device — anything you highlight it will automatically bring up in the Developer Tools app. This was quite nice.
Other than layout, basic state, and properties, this tool is pretty much a necessary one-trick pony:
- No Javascript debugging
- No console logs
- No exceptions or breakpoints
While it works the same with emulated and real devices, and it is available cross-platform, it’s a very specialized debugger. I would pull this up if I needed to debug my layout, or figure out where a component was incorrectly getting props from.
The saving grace here is that it also sets the highlighted component as a variable in Chrome Inspector — allowing you to dump the state of the property in Chrome Inspector. It’s actually a pretty neat trick.
In addition, there is a performance module here, that is a bonus and useful feature.
Moving on in my quest, I still haven’t found anything that helps me with the state of my application.
Maybe a 3rd window will help!
(You can use Reactotron.)
But let’s not get silly.
I stopped going after individual debuggers at this point, I was beginning to imagine a scenario where my task bar was taken over by 500 individual debugger apps — 26 for each letter of the alphabet (got to debug those ‘Z’s!), a couple for “if\then\else” clauses, a few more for some other stuff… Ugh.
So where exactly do I go now? These 3 apps are essentially the basics of debugging an application in React.
None of them control the run — so they aren’t useful from a configuration or testing management perspective.
None of them debug Native code — you’d still need Xcode or Android Studio\adb for that.
None of them are an editor, so you’d need another editor for that.
At this point, it was time to move off the React Native Documentation, and begin to explore.
The React Native Debugger is a step in the right direction. With this, the 3 apps most necessary are combined into a single app. The interface is still kind of clunky, but it’s truly USABLE. In a single App.
I’m extremely thankful for the person that chose to pull this together.
Sadly, this only really fixes one complaint — 3 apps. I now have 1 app, but other than that, I haven’t really made any progress forward.
Okay, moving on!
Next we have the Native Development Environments — Xcode or Android Studio.
Both of these are very helpful, necessary, and usable.
Only 1 is cross-platform (here’s a hint — it’s not Xcode).
None of them will help you dig much into the React-Native portion of your app — no state, layout inspector, etc.
So, unless you’re integrating React-native into a larger app, they probably aren’t going to be your go to.
You can however, edit code in these! So that is definitely a win on my list.
At this point, I was getting a little bored. Surely there has to be a better way? Is React-native so complex and\or special that it requires 3 different apps to do anything useful?
If I didn’t want to see just React-native logs, but wanted the device logs, did I have to run both Android Studio and a React-native tool?
It felt like I was using a lot of different, very specialized tools for a different purpose. It was cool they all worked together, but man, you really needed to just know. (YJGK = you just gotta know)
In addition, various bits had different functionality in 1 tool compared to another — for instance, Performance in Chrome Inspector meant something different than the Performance in React Native Tools.
Then, I read this article talking about how Facebook (the keepers of React Native) were developing the next generation of debuggers — Flipper!
Okay, I’ll bite.
What’s it about, and what does it do?
- Cross platform
- Javascript debugging
- All device and Javascript Logs
- Ability to manage devices — launch simulators
- Connect to multiple devices at once — Debug both windows and Android or whatever.
- Edit components on the fly. Watch your edits be reflected in real time in your app. Integrates with Layout Inspector in the app.
- Single-step debugging, breakpoints, watchpoints.
- Full Network debugging
- Loads of features — Flipper has a plugin based architecture, and supports a fair amount of useful features already, with more to come.
This debugger and its plugin suite is very useful. Best of all, the plugins offer a lot of additional functionality over other debuggers and development environments. And the ability to edit layout\components on the fly is genius!
I’m still missing something though:
- Integrated launch management — I find this extremely useful from my development environment, because it allows me to define configurations and use those same configurations in my unit tests. No sense replicating configurations in 2 or more places.
- Editing and Debugging in the same Window — even when I have a really nice text editor (I’m looking at you Atom!), it’s quite nice to use the same environment, key bindings, plugins, etc to debug my source. In addition, I don’t have to bring any changes I made in the debugger to test some fix back to my source editor.
- Extensibility — of the above debuggers, only Flipper is really extensible. The rest are fairly one-trick ponies that do one job (although they do at least do that job very well).
- As a bonus, I would like a nice, clean user interface. I hate when stuff looks bad.
I turned now to Visual Studio Code, the free editor from Microsoft. I love this editor — the extensibility of it, interface, plugins, etc.
It integrates with almost everything you can think of.
But… will it blend with React-native?
The good news is yes. You install the React-native Extension and you’re done!
So now, I can debug and edit in the same app.
- Cross-platform (with the ability to sync settings between Visual Code Instances on different machines)
- Javascript debugging, single-step, watches, breakpoints, exceptions
- Does NOT have layout editing or component view
- Controls the start and stop of the React-native server right from the IDE, no separate window required
- Hermes Javascript engine is currently experimental
- Handles iOS and Android as well as Windows and Mac OS
- No extensions like performance, network.
- Handles configurations — or definitions of devices and environments, such as Windows, Android Pixel, etc — right from the Run command palette. Will automatically spin up the right environment and ensure that your code is running on it. In addition, these same configurations can be used for testing and automated testing by the same IDE.
In a nutshell, I can now use the power of Visual Studio Code as an editor:
- pretty my code up automatically
- handle GIT pull\branch\etc
- run automated analyzers like lint
- use all of its powerful extensions
And combine that with a debugger that does 90% of what I want from a React-native debugger without looking like awful.
As a bonus, I get the power of its test infrastructure to unify my development across multiple platforms.
With VS Code, I am missing basic React-native layout and state debugging, but for that, I’m going with Flipper. With 2 Apps, I have covered way more functionality with a much better user interface than all the rest of these apps combined. The ability to edit components on the fly reduces my friction and makes me more efficient, and the plugins cover loads of territory that is necessary for mobile app development… in a way that nothing else on this list does.
In addition, the power of VS Code as an Editor and Test setup far outweighs the disadvantage of having 2 apps running, further increases my efficiency overall — and gets me a much higher quality app.
Even better, both of those Apps have a very nice user interface!
Links
General React-native Debugging Tool lists:
- https://reactnative.dev/docs/debugging
- https://www.sitepoint.com/tools-for-debugging-react-native/
- https://www.ideamotive.co/blog/how-to-debug-your-react-native-apps-like-a-pro
- https://blog.bitsrc.io/11-top-react-native-developer-tools-1e019462dd01
- https://medium.com/@AidThompsin/heres-how-you-debug-on-react-native-5039e3466010
- https://www.codementor.io/@ilovett/a-better-way-to-debug-react-native-redux-apps-gwbmkbq4v
React Native Debugger:
- https://github.com/jhen0409/react-native-debugger
- https://blog.logrocket.com/tips-for-fast-debugging/
Chrome Inspector:
- https://developers.google.com/web/tools/chrome-devtools
- Good Javascript Debug Reference: https://developers.google.com/web/tools/chrome-devtools/javascript/reference#stepping
- Tips for Setting Breakpoints: https://developers.google.com/web/tools/chrome-devtools/javascript/breakpoints
Flipper:
- https://fbflipper.com/
- https://github.com/facebook/flipper
- https://callstack.com/blog/debugging-with-flipper/
- https://heartbeat.fritz.ai/flipper-react-native-app-debugging-1d780115098e
React DevTools:
- https://medium.com/research-engineering-at-simply-technologies/react-native-debugging-like-a-god-9610ac2ffd12
- https://www.npmjs.com/package/react-devtools
Reactotron:
Visual Studio Code:
- React Native Extension — including Setup and Usage: https://marketplace.visualstudio.com/items?itemName=msjsdiag.vscode-react-native
- General tips on Debugging — https://code.visualstudio.com/docs/editor/debugging
- Quick Basic Guide to VSCode: https://medium.com/@tunvirrahmantusher/react-native-debug-with-vscode-in-simple-steps-bf39b6331e67
- A Great Complete Setup that My Setup Is Modeled After: https://medium.com/react-native-training/vscode-for-react-native-526ec4a368ce