The panel explores debugging: general debugging techniques, tools, and types of bugs you might encounter along the way. There might even be a Jamon tractor story or two..
The panel explores debugging: general debugging techniques, tools, and types of bugs you might encounter along the way. There might even be a Jamon tractor story or two..
This episode brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.
Helpful Links:
Connect With Us!
Jamon Holmgren:
Hey Everyone. Welcome to the React Native Radio Podcast, where we explore React Native together. I'm your host Jamon Holmgren. I'm joined by two of my three tremendous co-hosts. Adhithi, how are you doing this morning?
Adhithi Ravichandran:
I'm doing well. How about you?
Jamon Holmgren:
Doing well. We're really looking forward to this episode actually. This has been one that I've wanted to do for a while. So, definitely looking forward to it.
Adhithi Ravichandran:
Me, too.
Jamon Holmgren:
And Robin, how are you doing this morning?
Robin Heinze:
I'm doing great Jamon. Really happy to be known as tremendous. That made my day.
Jamon Holmgren:
Yeah, I'm going to be switching it up and using different synonyms.
Robin Heinze:
You got to shake it up.
Jamon Holmgren:
Harris is not here this morning. So Harris, I'm sure that you're going to be catching up and listening to your co-hosts at some point. Hi, Harris.
Robin Heinze:
Hi, Harris.
Adhithi Ravichandran:
Hello.
Jamon Holmgren:
He's probably in Alaska or something.
Robin Heinze:
We miss you.
Robin Heinze:
Yeah, probably like he is moving west. So, Alaska would be.
Adhithi Ravichandran:
He's probably is Seattle now.
Jamon Holmgren:
That's the next step. Okay. This episode is sponsored by Infinite Red. Infinite Red is a premier React Native design and development agency located fully remotely in the USA for a lot longer than the pandemic year, actually way back to...
Robin Heinze:
We were quarantining before it was cool.
Jamon Holmgren:
We were the original quaranteam. With years of React Native experience, since React Native was released and deep roots in the React Native community, we are the hosts of Chain React and publish the React Native newsletter, Infinite Red is the best choice for your next React Native app. Hit us up at hello@infinite.red, or just email me directly jamon@infinite.red. All of the complaints about today's podcast will go to robin@infinite.red.
[Robin laughs]
Jamon Holmgren:
Hit us…I already read that part. You can learn more on our website, infinite.red. Okay. So, today's topic. We are talking about debugging React Native apps.
Robin Heinze:
Jamon is really excited about this topic--
Jamon Holmgren:
I am.
Robin Heinze:
...because his apps always have a lot of bugs.
Jamon Holmgren:
Well, okay true. Yeah. I don't have a good comeback.
[Robin laughs]
Jamon Holmgren:
Let's talk about general debugging techniques. Here's thing. I think that before we can get into tools, we have to talk about just techniques in general, because when I was a kid learning to program in QBasic, I didn't have all these fancy tools. QBasic actually came with some reasonable, like you could step through codes, you can do like break points and cool stuff like that. I was honestly kind of surprising considering that it was in 1991 or 1992 or something like that. But, there are some basic techniques that I learned even back in those days that still apply today. And then new ones that have kind of come along as I've progressed through my career. So, the one that I would probably start with is that a common mistake that I see new developers make and even experienced developers is that they try to guess at what's happening under the hood. They see something wrong and they make some assumptions, like immediately there's some assumptions. There's something wrong, I think that this third-party library just broke it. Or I think that this change that I just made just broke it. Generally speaking, they are probably right, because usually the thing they just did often will be the culprit, but when they're not right when they're wrong and they continue down that vein of having that assumption, then it can be very frustrating because you're trying to fix something that really isn't the problem. And often they don't know how, or it's too difficult to get the system to really give them feedback on what is actually happening under the hood. So, I have this kind of basic thing that I've told junior developers that I've trained in the past. Before you can fix it, you have to break it. Break it in a new way, okay? I can't tell you how many times I've been trying to work on a bug and then found out I was editing the wrong file for example. And it wasn't even doing anything.
Robin Heinze:
All the time.
Jamon Holmgren:
Yeah. So what I try to do is I put a nonsense function call at the beginning of whatever I'm working on. Did it break in a new way now? Or do you just introduce a syntax error? Does it fail to compile? Can I break it in a new way so that I know where I am like an anchor point. This is where I am.
Robin Heinze:
Or even just put it in alert.
Jamon Holmgren:
Yeah.
Robin Heinze:
If you put it in an alert ...
Adhithi Ravichandran:
Mhm.
Robin Heinze:
… and it doesn't fire, you know that you're not running what you think you're running.
Jamon Holmgren:
Exactly. So, that's kind of like, step one. You need to make sure that you are in the right file editing the right thing that it's even getting to the code that you think is the problem.
Adhithi Ravichandran:
Along with what Jamon was saying. I think it will be nice to have junior developers also when they onboard, we could get them set up with all the debugging they need irrespective of the technology it is. Because even when I was a junior developer, I was kind of hesitant to ask questions ...
Jamon Holmgren:
Mhm.
Adhithi Ravichandran:
... to whoever was on the team, so I used to think I'm just going to try to figure this out. And I would try to do things by trial and error and be like, maybe is the bug, let me try fixing this and then spend days without realizing there are better ways to debug and I probably never even debugged. I definitely agree that this is kind of an initial start, a problem for junior developers.
Robin Heinze:
It's also just a really hard thing to learn and to teach. Like, I feel like most of the debugging skills that I have, I learned through pairing, just like you just have to watch someone who knows how to debug.
Adhithi Ravichandran:
Right. Yes.
Robin Heinze:
And like fix the problem because it's at some point it just becomes kind of an intuitive thing.
Jamon Holmgren:
I agree with that.
Adhithi Ravichandran:
And It comes with practice too depending on which tech stack you're at and things like that.
Robin Heinze:
Exactly. If you first learn how to program in Ruby, there's different techniques and different ...
Jamon Holmgren:
Yeah.
Robin Heinze:
... tool sets.
Adhithi Ravichandran:
I like to think of this like a doctor's office visit where you go with a problem and then they take all these series of tests to kind of diagnose what your health issue is before they give you medication or treatment, rather than be like, "Oh, I think this is probably Malaria". And then just give you ...
Jamon Holmgren:
Mhm.
Adhithi Ravichandran:
some meds.
Robin Heinze:
There's also probably a step before even what we just talked about which is knowing how to read an error message ...
Jamon Holmgren:
Mhm.
Adhithi Ravichandran:
Mhm.
Robin Heinze:
... because, it's a step that a lot of new devs tend to skip.
Jamon Holmgren:
Mhm.
Robin Heinze:
If you know how to read an error message, it can point you exactly to where the issue is. And you might not need to do a ton of bisecting and manual debugging.
Jamon Holmgren:
Yeah. it can be kind of difficult because it is a lot of texts usually. There's a huge stack trace. It may be kind of scary ...
Robin Heinze:
You have to know what you're looking for.
Jamon Holmgren:
... sounding text. Yeah, exactly. You have to know where within the stack trace something relevant might be, and I've seen some situations where someone will read the stack trace and get sidetracked by the wrong thing where ...
Robin Heinze:
Mhm.
Jamon Holmgren:
... they're like, "Oh, well, it must be a problem in RCTView" There's a bug in React ...
Robin Heinze:
Mhm.
Jamon Holmgren:
... Native, and it's like, well, that's ...
[Adhithi laughs]
Robin Heinze:
Knowing how to look through a stack trace and find like, you can ignore all the files that you did not create.
Jamon Holmgren:
Usually.
[Jamon laughs]
Robin Heinze:
And you find the one line that's like a file. That's actually something that you wrote ....
Jamon Holmgren:
Yeah.
Robin Heinze:
... and that's most likely a good place to start.
Jamon Holmgren:
Exactly. And then you can start by really kind of bisecting. So, I'm not talking about git bisect, although git bisect can be very powerful if you are trying to find where a bug is in a history of commits. But, I'm really talking about taking chunks of code and eliminating them as factors as possible sources of a particular error. Let's say you're getting a strange crash and it's not really giving you a helpful back trace, which unfortunately has been the case in a lot of React Native apps, a lot of React Native versions. They’ve gotten better about it, for sure. But you need to figure out where is this crash even happening? So, you start by maybe short-circuiting a whole section of code and say, "Does this happen anymore?" "No, it does not". "Okay, well, let's go to the middle of that code and short circuit just the rest of it, like you run like half of it". "Did it happen there?" "Yes, it did". "Okay well, it must be in the top half". And now you just keep dividing that in half, it's like 20 questions. You're trying to cut down ...
Robin Heinze:
Yeah.
Jamon Holmgren:
... possibilities until you get to the line of code that's causing the problem.
Robin Heinze:
It's basically like a logical technique. It's like trying to guess a number that someone is thinking of in their head.
Jamon Holmgren:
Mhm.
Robin Heinze:
And you're like, "Okay, is it greater than a 100?"
Jamon Holmgren:
Right.
Robin Heinze:
"No". Okay. So, it's less than a 100. You're like, "Okay, is it greater than, or less than 50"?
Jamon Holmgren:
Mhm.
Robin Heinze:
It's just sort of logical deduction.
Jamon Holmgren:
Mhm.
Adhithi Ravichandran:
You're kind of untangling the layers, one by one and ..
Jamon Holmgren:
Yeah.
Adhithi Ravichandran:
... then reaching kind of isolating ...
Jamon Holmgren:
Isolating.
Adhithi Ravichandran:
... the real problem. Yeah.
Jamon Holmgren:
So, I have a tractor story.
Adhithi Ravichandran:
Uh-huh, lets here it.
Robin Heinze:
Tractor story.
[Jamon laughs]
Robin Heinze:
That should be a new segment. Can we make out a new segment?
[Jamon and Adhithi laugh]
Jamon Holmgren:
Jamon's tractor stories. I have a tractor, I don't know if people know this. And I was going to add some lights to the ROPS the rollover protection system, which is a very fancy name for a rollover bar, which is just behind your head when you're driving it. Anyway, I wanted to put some LED lights on it, just to light things up if I'm using my tractor in dark conditions. I did a bunch of research, and this is 12 V wiring. You have to come off of the battery or off of another wire and you have to tie in and you have to make these connections all the way through. You have to run your wires properly. You have to have the right wire connected to the right wire to have a closed circuit and stuff like that. And at its most basic level of computers kind are just circuits and stuff. So, it's not that different in some ways. So what I did, I kind of use my debugging technique to figure out the best way to do this. I needed to know if there was a circuit in the back of the tractor and I needed to know, is their power there? And not only that, but what is the red-- the red wire obviously should be the positive side of the, you have positive and negative, right? So the, the red should be positive, the black should be negative. How do I figure this out? So, I could just plug in the lights and see if they work. That would be one way to do it.
Adhithi Ravichandran:
Mhm.
Jamon Holmgren:
Or you can have some way to measure it, some way to check it, some way to check your assumptions all along. So, I actually bought a tool called a multi-meter and there was a long discussion on Twitter, how you're supposed to pronounce this.
[they take turns trying to pronounce multi-meter]
Adhithi Ravichandran:
Multi-meter.
Robin Heinze:
Multi-meter.
Jamon Holmgren:
Multi-meter. Multi-meter. I don't know.
Robin Heinze:
I'm pretty sure my husband calls it a multi-meter.
Jamon Holmgren:
That's probably right in America. Anyway, it's a machine you have two like wire probes that you can put into, you can contact them with the wires and then it gives you readings on it. And what I thought was really cool about it was I could actually connect it up to that turn on the key. And I had to figure out, for example, is this switched or not? When I have the front lights on, is it powered? Or If I turn it off, is it still powered? When I turn the key off? Is it still powered? I don't want these lights to just be on, right? So, using this tool, I was able to determine, yes, I have 12.7 V at that connection, the red was positive. If I switched the two probes, then it went negative 12.7 This tool allowed me to check my assumptions, to check that I had power where I thought I had power. Then from then on, whenever I plugged into that, I knew that that's not the problem. Like that's got what I need. Everything's good up to this point. Whenever I'm wiring in the rest of the lights, if they're not working, it's something I did. It's not something the tractor had some problem with it. So, to bring this back to our topic, debugging, you have to check your assumptions. Too many times I've had people that I've helped fix a problem and they say, "Well, I can't figure out what's wrong with my probe." Oh.
[Robin and Adhithi laugh]
Jamon Holmgren:
"I can't figure out what's wrong with my code. Every time I make a change, it's not fixing the problem." And I'm like, "Well, is it even your code that's running? Is it even your code that's causing the problem, or is it some other code?" Just checking those assumptions, having some sort of way to measure and report back, whether it's just an alert or console.log or some of the tools that we'll get to a little bit later, it's really important. And the other thing is for production, making sure that you have crash reporting in production, too. Because if someone's just reporting, "Hey, it crashes when I click on this". That's not all that useful, but if you have a back trace and somewhere to start, then you can do a lot more.
Robin Heinze:
Hey Jamon, can you tell that to my clients who said they didn't have time for us to implement crash reports?
[Jamon laughs]
Jamon Holmgren:
Yeah. You will spend far more time or just like never fix stuff If you don't have crash reporting. Crash reporting is so important. And I can't tell you how many times I've been doing this. For 15 years now I've been consulting, I can't tell you how many times it's been like, "Well, you know, it's going to be kind of a pain to set that up."
Robin Heinze:
Well, it's going to be way more of a pain when your customers are telling you that the app's not working and you don't have any way to figure out why.
Jamon Holmgren:
Exactly. Okay, let's say you're in a situation where you're like, okay, I'm running into this situation where the state of my app is not what I think it should be. I click this button and instead of doing this, it's doing something else. You could just try to like console-log your way out of it, or you could set up a tool like React Dev Tools, or React to Tron or Flipper or something like that, and get it to tell you what your state is at every step of the way. When you do that, you've now have just so much more information about what's happening and often your assumptions will be wrong. Usually when you're beating your head against the wall, it just means that your assumptions are wrong. By the way, check this out. Got a Kubota hat.
Robin Heinze:
Oh my gosh.
Jamon Holmgren:
That's my tractor brand.
Adhithi Ravichandran:
Nice.
[Adhithi laughs]
Robin Heinze:
Do you have a picture of your tractor framed on your desk, too?
Jamon Holmgren:
Good idea.
Robin Heinze:
You can put it in front of the picture of your kids.
[Jamon, Adhiti and Robin laugh]
Adhithi Ravichandran:
So, while we're talking about general debugging tips, have you heard of the rubber duck debugging method?
Jamon Holmgren:
Mhm.
Robin Heinze:
It's my favorite.
[Adhithi laughs]
Jamon Holmgren:
Explain it though to our listeners, Adhithi.
Adhithi Ravichandran:
So, the rubber duck debugging method is basically, you're going to take a rubber duck and go in front of your laptop and explain to the rubber duck-- because the rubber duck doesn't know what's going on with your code-- line by line what's going on and kind of just explain what the problem is to the duck. And that's considered a pretty efficient technique for debugging code or fixing bugs in general because most developers do have a problem in explaining this to a co-worker or somebody who doesn't know much about it. And the idea is that when we try to teach a concept to somebody who doesn't know anything about it like the rubber duck, we would get a better understanding of it. And that could potentially lead us to figuring out where the issue probably is and gives us a deeper sense of understanding the problem really. So, that method would make you be like, "Oh yeah, while I'm explaining to the rubber duck, I figured out where my bug was." That sometimes work. I do think for me, teaching really helps. Teaching online courses really helped me kind of go over the concepts and have a deeper understanding, because I need to teach this to someone who doesn't know it so I better know it really well. So that's the same concept with rubber duck debugging tool.
Robin Heinze:
I would say like hmm, five times out of 10 when I ask for help on something in a Slack channel, by the time I finished writing it up and hit enter, I've usually figured out what was wrong and my next response is usually, "Nevermind, figured it out".
[Jamon laughs]
Adhithi Ravichandran:
Uh-huh. Yeah.
Robin Heinze:
Because like going through the problem enough to write it out will sometimes reveal things that you were--
Jamon Holmgren:
It's very true.
Robin Heinze:
just missing. Also my rubber deck of choice is Lego Hermione.
Jamon Holmgren:
Mmm. I like it.
Robin Heinze:
Which those of us on the Zoom call right now can see, but our listeners cannot. I have a little--
Adhithi Ravichandran:
She looks awesome.
Robin Heinze:
I have a little Lego Hermione on my desk.
Jamon Holmgren:
You know what I need? I need like a little tractor for my rubber duck.
Robin Heinze:
Yes.
Jamon Holmgren:
Like a little toy tractor. That would be perfect.
Robin Heinze:
Yes.
Jamon Holmgren:
There's got to be a little--
Robin Heinze:
I am writing that down.
Jamon Holmgren:
Kubota tractor toys out there.
Robin Heinze:
I'm writing that down.
Adhithi Ravichandran:
I use my daughter sometimes.
Jamon Holmgren:
Oh, you just explain it to your daughter?
Adhithi Ravichandran:
Uh-huh.
Robin Heinze:
Explain like I'm two. Explain like I'm three.
Adhithi Ravichandran:
Yeah, but these days she's asking, you know, follow questions and I'm like uuh...
Jamon Holmgren:
Is she looking for a job?
Adhithi Ravichandran:
Nevermind.
[Adhithi laughs]
Adhithi Ravichandran:
She is smarter than I want her to be so she is not doing a good rubber duck job these days.
[Jamon laughs]
Jamon Holmgren:
Yeah. That's great. So, it's all about eliminating variables really and getting metrics in place and challenging your assumptions and making sure that you have all the right information. And then often, the debugging part is pretty straightforward. You find that you misplaced something a parentheses or something along those line. Another thing that you have to make sure that you are doing is making sure that you can reliably reproduce the bug. So when you have a bug that only shows up sometimes, and you're just not sure, and you're just kinda like wildly clicking around your app or you're tapping around your app. That can be very frustrating as well. So, making sure that you document or like very carefully take note of all of the steps that it took to get to the error condition, whatever it might be, whether it's an, a crash or if it's just the wrong state. It's extremely important to make sure that you can reproduce that reliably. Now, sometimes it's not always possible. For example, race conditions can be very difficult where you have two pieces of code and when one finishes before the other, it's asynchronous, then it causes the bug. And when the other one finishes first, then it's fine. That can be very frustrating. But even in those cases, usually you can get to a state where you can reproduce it somewhat consistently. And when that happens, then you know that it's probably some sort of a race condition.
Robin Heinze:
I'd say race conditions are one of my least favorite bugs to encounter.
Jamon Holmgren:
Yeah.
Robin Heinze:
Especially when there's an API involved.
Jamon Holmgren:
Yeah, totally.
Robin Heinze:
Or like a database involved.
Jamon Holmgren:
Yeah, they can be very frustrating and very difficult to debug.
Robin Heinze:
And difficult to resolve too, in some cases.
Jamon Holmgren:
Even when you know what's happening.
[Jamon laughs]
Robin Heinze:
Yeah, exactly.
Jamon Holmgren:
That's when you just put sleeps in, right?
Robin Heinze:
Throw in a loading spinner.
Jamon Holmgren:
No to audience. That is not what you do. Yeah. So when it comes to React Native itself, let's get into more specifics. The first place that I think I would send people is to go look at the reactnative.dev website, the debugging guide. There's a lot of good information there.
Robin Heinze:
It's pretty thorough.
Jamon Holmgren:
Yeah. It has a lot of great stuff. Within your simulator, here's some tools they have. The first thing that they mentioned is the in-app developer menu. So you have, if you hold in iOS, if you hit command D or if you're an Android on Mac, you hit command M or if you're on windows or Linux, you hit control M, it will pop up a menu for React Native in development mode. This is disabled, otherwise.
Adhithi Ravichandran:
Mhm.
Jamon Holmgren:
You can tap reload, you can start your remote JSD bugging, you can enable and disable library, load and hot reloading. There's a few other things too, the inspector and performance monitor. We will get to those. But this, obviously, is kind of a first place to start because if you have a bug, sometimes the best thing to do is just refresh. Reload the app.
Robin Heinze:
Just be careful. I've gotten into scenarios where weeks will go by and I realized that I've basically just refreshed every time a certain bug happened, but really there's something that I actually need to fix because an actual user will not have the ability to refresh the app.
[Robin laughs]
Jamon Holmgren:
Right.
Adhithi Ravichandran:
That's very true.
Jamon Holmgren:
Yes. That's a good point. And it's a good idea to probably test on a regular device so that it's not as not as simple to just reload the app in more of a condition that the user would be using.
Robin Heinze:
Also test in release mode.
Jamon Holmgren:
Yes. Yeah.
Harris:
Because that can sometimes change how things load.
Jamon Holmgren:
Yeah. So you would deploy to your app using release mode which would disable some of the things, some of the options you have when you're in debug mode or development mode, I should say. I've noticed that the reload sometimes gets stuck. I have kind of this escalating process I use. First, I'll just command R if that doesn't work, then I'll hit command D and I'll hit click reload. And if that doesn't work, then I'll go up to the menu and I'll click shake device, which I think opens up. Well, actually I think on expo, it opens up the debug menu. Does it also on….
Robin Heinze:
It’s on the vanilla React Native too.
Jamon Holmgren:
Okay, cool. And so you can hit shake device and then hit reload. And if all else fails, then just swipe it away in your simulator.
Robin Heinze:
I looked into that a little bit and I found that there was a specific issue with iOS 13.4 simulators, where the input focus kept getting switched so that your keyboard inputs wouldn't trigger the menu. So, I've started using iOS 13.3 simulators, and I have less of a problem with the menu not opening.
Jamon Holmgren:
Opening it up. Yeah. That does seem to be something that's been around for a while though, that tends to happen but yeah, that's good to know.
Robin Heinze:
I have to admit there some options in this menu that I don't think I've ever used.
Jamon Holmgren:
Yeah.
Robin Heinze:
Like what what's SIS trace?
Jamon Holmgren:
I think that actually-- and Robin and I were talking in our pre-podcast time-- that there are actually in my show prep, I found a lot of tools that we haven't used or don't use fully. I feel like this is a fairly common thing. Like people don't generally invest probably enough time, and I'll include myself in this, in learning the debugging tools that would make their life so much easier if they just knew them. And I agree. Like I open up this in-app developer menu and there are things in there that I don't use very often or at all. And so investing some time in that is pretty good. We're going to go through that list of things. So, obviously reloading. Remote JS debugging is the next one. And with that, you can use Chrome, Chrome developer tools to debug the JavaScript part of your app remotely. It opens a new tab with a localhost website that pops up, and then you can also use React Devtools to kind of inspect the React, you know, the React components within it.
Adhithi Ravichandran:
Or you could just use React Native Debugger, which does both.
Jamon Holmgren:
Mhm.
Adhithi Ravichandran:
It's kind of like a standalone tool, you install that. When you have that installed and open and you hit start Remote JS debugging your React Native Debugger is going to open up and basically do the same thing. It's going to have your Chrome, it looks kind of like Chrome, It has your Redux Dev tools and everything's set up already. It's kind of cool.
Jamon Holmgren:
Yeah. That's a good one. We'll link to that in the show notes. There's a lot of great functionality in there. You can see console logs, you can look at network and performance in your memory just to kind of learn all of that.
Adhithi Ravichandran:
It's really cool if you're using Redux because you can keep--you probably have a ton of stuff on Redux and you can see that the states diff--so whenever a state changes, you can hit the div tab and look at what really changed and it'll highlight that for you. So it's been really useful. I've used it for a couple of years now, and I really love it.
Jamon Holmgren:
You can also do breakpoints, and when you do a breakpoint, you can actually examine the active threads that were running right before the breakpoint was used and also the call stack of the current thread where the breakpoint was executed. So it allows you to really see, how is this code arrived at? How did we get here?
Adhithi Ravichandran:
Yes. And recently they also added the Apollo Client DevTools. So if you're using GraphQL with Apollo, you can use these devtools as well. So it's kind of like an all in one box that you can use for React Native debugging.
Jamon Holmgren:
You can use breakpoints in Google Chrome directly. So if you put a breakpoint in--and how actually do you add a breakpoint?
Adhithi Ravichandran:
You can add your breakpoint within your, basically your source code. When you open your React Native Debugger, you can pull up the source folder and basically go into whichever components or container files you want, and add the breakpoint there within the React Native Debugger.
Jamon Holmgren:
Got it. So it allows you to just click on the gutter and add the breakpoint there. This is not a tool I've used, so that's pretty cool. That would be very...
Adhithi Ravichandran:
It's kind of just like what you would do on Chrome, but just neat with everything in a box.
Jamon Holmgren:
Yes. So that's very, very helpful. So that's called React Native Debugger, and you can find that--we'll link to that. There's obviously React devtools. You can inspect React components. You can see the props for the React components, and you can also use--so I'm going to actually talk about Reactotron a bit too. So Reactotron is another similar tool that we make at Infinite Red. It allows you to--it's more focused on state and also timelines. So you can see debugging logs and you can log out objects and browse them and stuff.
Robin Heinze:
It shows you actions, like async storage actions, network requests, state.
Jamon Holmgren:
Yes. And the state part is pretty cool because you can watch just particular parts of your state and see when they change. You subscribe to them basically. And this can work for Redux. We've got Redux-sagas. You can use on a MobX-State-Tree as well. It allows you to look at any of your state. You can also save snapshots of state. And so that can be very helpful as well. You can replay snapshots of your state and get into a certain state. You can do custom, you can add custom buttons to Reactotron that allow you to click the button and it runs code in your app. So let's say that you want to have a...
Robin Heinze:
Really useful.
Jamon Holmgren:
What do you use it for, Robin?
Robin Heinze:
We use it for things like--anything you can think of pretty much. Like if I want to clear the navigation state, because I've added some screens, and it's in a funky place, clear the navigation state, clear the store. I use it to open special debugging screens or open screens that I maybe don't have a path to through the UI yet. Pretty much anything you can do in code, you can have Reactotron do for you.
Adhithi Ravichandran:
How do you spell Reactotron?
Robin Heinze:
Reactotron is r e a c t o t r o n. Or is there an O in there? Oh my gosh.
Adhithi Ravichandran:
Because when I Googled it, I got Reactoon, which is a conference. Okay. Reactotron, t o t r o n.
Jamon Holmgren:
It's r e a c t o t r o n. That's actually a little bit of a funky spelling, but yes, it runs on windows, it runs on Mac, it runs on Linux. It's an electron app. Pretty lightweight though. And I do know that we get a lot of people telling us that they really love using it, that the user experience--it's more limited than something like React Native Debugger, but it has a good kind of developer experience around it. So it's more, I think, polished in some ways in terms of what it does. And, of course, the benefit of being able to inspect MobX-State-Tree state is a pretty big deal because we use a lot of MobX-State-Tree at Infinite Red. By the way, I don't know if I've announced to the podcast listeners that I've taken over MobX-State-Tree as the primary maintainer. I did that recently and I'm building a core team around MobX-State-Tree. We actually had a ton of interest. I have, I think, over 20 people now who are interested in contributing to MobX-State-Tree. So, stay tuned for that. We might talk about that and more in the future.
Adhithi Ravichandran:
That is pretty awesome.
Robin Heinze:
Yes. I imagine we'll have an MST dedicated episode.
Adhithi Ravichandran:
So it could do both MobX-State-Tree and Redux then?
Jamon Holmgren:
Correct. Yes. It does plugins for both of those things. And you can build your own plugins for other state systems, whether it's unstated or any of these others. You can build your own plugins. It's pretty straightforward. It's also built into Flipper. So we'll talk about Flipper probably more in a separate episode. Flipper is kind of its own topic in and of itself. Of course, Flipper comes from Facebook, fbflipper.com, I think it is. Or is it flipperfb? Sorry, I don't know. Google it. It's a desktop app that allows for inspecting more Native stuff. You can actually deep dive in--it was actually originally built for non React Native debugging, and then it has been expanded to allow that. Reactotron is, I think, the first plugin released for Flipper. Facebook actually approached us and said, "Hey, would you mind building Reactotron into Flipper as a plugin? So we did that. You can get it as a standalone or you can you can use it as a plugin in Flipper itself. Either way works really well and fits in really well with the Flipper ecosystem because Flipper needed that kind of state management side of things, as well as just better support for logging and stuff.
Robin Heinze:
I find the network requests logging extremely helpful in Reactotron. When I'm working with a client who's building an API for us, being able to snapshot the requests that we're making and the responses that we're getting, and I can paste it to them as Karl, as Jason, as whatever. And so to see exactly what's going on with the network request is really helpful. I would say one thing that Reactotron doesn't do that can sometimes be a big piece of debugging is Native logging. And I don't actually know if any of the debugging tools out there really handle Native logging.
Jamon Holmgren:
Flipper does. So that's where I think Flipper--Flipper plus Reactotron, I think works really well because Flipper will give you native crashes and native logs. And so, yes.
Robin Heinze:
Because there's some times where you really just need to see the native logs. I know there's been some crashes where it's crashing before it even gets to the JavaScript layer and you really don't have any other choice than to peek into Logcat or the Xcode logs.
Jamon Holmgren:
Flipper also comes with a layout inspector, and that's native, native layout inspector. That can be very helpful, especially if you're trying to figure out, are we building this in a way that is getting way too nested for performance reasons, and just other things like that.
Robin Heinze:
So how does that differ from the inspector in the React Native debug menu?
Jamon Holmgren:
The React Native Debugger is inspecting more the React part of it, the JavaScript part of it, like you have your components and what props are being passed in and whatnot, where Flipper is inspecting what's rendered, the actual native view. So having both is--honestly, I would use all these tools. I would have all of these tools at my disposal. I would learn them all, have them all available. Reactotron is free. So is Flippers, so is React Native Debugger.
Adhithi Ravichandran:
So Flipper, is it available--I guess it's in the latest version, right? You have to be on 0.63, is that right?
Jamon Holmgren:
Yes. That's correct. Yes, you have to be on--is it 0.63 that requires it?
Robin Heinze:
I've heard it's 0.62.
Jamon Holmgren:
62 point something. I don't know. It has to be--I guess Flipper would...
Robin Heinze:
Yes, 0.62.
Jamon Holmgren:
0.62. Okay, perfect. So you do need to be on a relatively recent React Native version in order to use it, but if you can, I would definitely have it and then have Reactotron inside of it as a plugin or as a standalone app, if you prefer it that way.
Adhithi Ravichandran:
And if you're in 0.63, I guess, or even 0.62, the other cool thing you can use is LogBox for basically console logging, alternative for React Native, it's kind of a neat display that you have, which has a red box and a yellow box. And you're going to display your console logs on your--you can see it on your emulator, and if you don't want to see any of it, you can always ignore it. But it's kind of nice while you're debugging, you can add all these logs and it's going to basically alert you with everything that you need to know from the log.
Jamon Holmgren:
There are a lot of people that worked on that. I want to shout out to Rick Hanlon, who has done a lot of the work on, including designing better errors around this. But yes, LogBox has been fantastic since it came out. It's just so much nicer experience. You can dismiss some types of errors so that you can see what state your app was in before the error occurred. Some errors like syntax errors, you can't dismiss, obviously, because it didn't build anything behind it. But for unhandled exceptions and stuff, it can be very, very helpful. And it's just a more friendly--I remember back in the day, it was all just like this big, bright red screen, with a massive text all the way through it.
Adhithi Ravichandran:
It's the red, red screen of death.
Jamon Holmgren:
The red screen of death. Exactly. If you've been working in react native for a while, you'll remember that. But it's so much nicer now with the new LogBox. Speaking of Native logs, you can also see them in the terminal. If you do NPX React-Native and then Log-iOS or Log-Android, and those will show up in your terminal. So if you don't have access, if you don't have Flipper, you can still run those and see what the Native logs are. Obviously, you can also run it in Xcode or in Android Studio instead of from your terminal, and go and use their debugging tools, including seeing logs in their console.
Robin Heinze:
Pro tip, if you're using the command-line logging, it's sometimes helpful to pass in a grep argument for your app name, or I think capital React, capital Native because there's sometimes a lot of noise from the other processes going on in the simulator. So it may be helpful to use grip to filter down what you're looking at.
Jamon Holmgren:
This is one thing that I've found quite frustrating from a lot of libraries, is they tend to just spawn tons and tons of warnings, and errors, and random stuff that doesn't actually affect anything. It's not anything we can affect at the moment. Maybe it's some problem internally to React Native, or some problem otherwise. The signal to noise ratio is just so, so bad sometimes.
Robin Heinze:
Deprecation warning.
Jamon Holmgren:
Deprecation warning.
Robin Heinze:
That you can't change.
Adhithi Ravichandran:
The other thing to note is having too many console dot logs would hit your performance. So make sure that while you're debugging, you have them. And then you can have a setting where you turn off all the console.logs so you don't send that to prod because that's going to slow your performance.
Jamon Holmgren:
Definitely. That's a big one. I'd like to move into the React Native Inspector itself. So in the developer menu that pops up on the device itself, you have a few different options. And one is the React Native Inspector. It's actually an on-device or on-simulator inspector and allows you to inspect items in--like, you can tap on items in your view and see information about them. So that can be very helpful. Have you two used that inspector at all?
Adhithi Ravichandran:
Yes. I use it all the time.
Robin Heinze:
Yes. All the time.
Adhithi Ravichandran:
Because that's the easiest spot for, especially UI related, styling related stuff. When my emulator is turned on, if I know there's something off with the padding, something doesn't look right, I just go in there and it's going to list out all your styling information. Like it would tell you what's the margin, font, size, color, everything. And it even has some kind of a small picture where it'll show you the measurements of that specific element. And that's really useful.
Robin Heinze:
This can be really helpful.
Adhithi Ravichandran:
So for UI related stuff, I use it all the time.
Jamon Holmgren:
Very cool.
Robin Heinze:
Figure out if you've got flex one on something that you didn't expect. Also, tried and true, don't be afraid to use border color red border with one. I love it.
Jamon Holmgren:
Old school debugging. I love it.
Robin Heinze:
Old school.
Jamon Holmgren:
Where's this box? Maybe it's not even--I've had situations where...
Robin Heinze:
It's not even there.
Jamon Holmgren:
It's not--it's just collapsed like it's just not even there.
Robin Heinze:
Exaclty.
Adhithi Ravichandran:
Yes. I definitely like it because it's easier than going into your style sheet and looking for the style, so you just--this is just faster and easier.
Jamon Holmgren:
Yes. I'm going to come back to this again, but I see this too often with new developers, they try the trial and error far too much, and they don't just go in and find out what exactly is going on before they start doing that. So having these tools available and being able to get a complete picture of what's happening, like a mental model of what's happening, is so, so important to debugging. You're going to beat your head against the wall for three days versus, get the tools in place and be ready to go in three hours.
Robin Heinze:
I mean, at the end of the day, and this is actually one of the reasons I got into this profession and enjoy coding so much, is that computers don't do anything of their own accord. Everything that they're doing has a logical reason behind it. You just have to find it.
Jamon Holmgren:
Talking about performance, so performance issues are bugs as well. And there are some tools in place--during show prep, I found an amazing article by Louis Zawadzki, I think, I'm sorry if I didn't say that correctly, on blog.bam.tech. It is about debugging React Native performance issues. It actually was, I think it came out in September so it's fairly recent. Did a great job with this. He goes through reproducing the error, reproducing the issue, and using thread profilers on the device to see, are we getting RAM issues? What UI FPS are we hitting, et cetera, not just UI, but also the JavaScript thread as well. You want to be hitting 60 FPS, right? Profiling, JavaScript, timing, debugger, looking through the tree of JavaScript calls. It's not like a super, super long article, but it has lots of screenshots and it has a lot of information. It also talks about Flipper and how it can help you. So definitely check that out and read that for performance help. There's also a perf monitor in the simulator itself, and he talks about that. So that is, I think, a good place to start. What other tips for performance debugging do you have?
Robin Heinze:
Well, to be quite honest, Jamon, I think performance is one of those things that a lot of us, even experienced developers, tend to put last priority. It's really easy to say, "Well, it's working, it's just slow."
Jamon Holmgren:
Yes. Just like me.
Adhithi Ravichandran:
With performance, I think, debugging kind of is--I don't know if that's the right word. I guess you do profiling. And I would do checks, like, okay, is Hermes turned on? Do we have that in this project? If not, do it. And then we would look at simple things. Like if you have these large lists, are you using the right component? Are you using section list or flat list? Are you using keys within your views for list items? So it's more like a code check. And then I would make sure there's no console logs just flooding the code base. So just the checklist. I don't know if you recall, we talked with Gant the other day about the checklist before you go into prod with the React Native app. And that addresses some of these performance checklists as well. So I would do that quite often too. And that usually helps. But if we're seeing specific issues, there's also things like with the animations, we need to make sure in React Native, we're using the Native thread rather than the JavaScript thread. There's just a bunch of things I check off and that usually helps.
Jamon Holmgren:
I think that performance is going to be probably a full episode in and of itself, to be honest. There's a lot to go over with that. Maybe we could get someone on the program who has some good experience around this and interview them. But really good information there, Adhithi. There's a ton more resources that I found while I was doing show prep for this show. But I think that we can probably call that a wrap. That was definitely--there's a lot more to debugging, of course. I actually consider debugging to be one of my probably strongest parts of my skillset. Probably a big piece of that was that whole Q basic days, I didn't have stack overflow. I didn't even have the internet. I couldn't go look it up. I had to figure it out myself. So if I wanted to finish whatever it was, it was just trial and error. A lot of old school debugging techniques came out of that for me. And just the importance of knowing like, am I in the right spot? Am I even editing the right file? Are my assumptions correct? Really, really helped me further on. Then from there, just learning the tools and learning what tools are available, how they work, how to implement them. You can go as far as diving into memory issues and memory leaks. There's so much more to this topic, but I think that that's a pretty good stopping point there. Okay. Now we come to the part of the program where we talk about weird bugs. Does anybody have a weird bug?
Robin Heinze:
Well, we have a weird bug. It's actually one of those bugs that we have kind of found ways around, but haven't totally pinpointed how to avoid it. But this is on a project we're working on right now that uses a monorepo to do web and mobile with some shared code. One of the challenges with that is we keep running into circular dependency issues. How that shows up in MobX-State-Tree is, once in a while, we'll get this really vague error which says "Expected MobX-State-Tree type as argument one got undefined instead" on a line of code that usually works pretty straight forward where passing a model as a type should work. Every once in a while we get this really cryptic, vague error. Well, we're pretty sure it's happening because of circular dependencies, which means when a file is importing something from another file, but then that file also is importing something from the first file. And sometimes it can happen in kind of a roundabout way through a chain of imports and exports. It isn't always just one file to one file. So it can be kind of hard to find, but apparently this is what MobX-State-Tree does when you have a circular dependency.
Jamon Holmgren:
It'll just be undefined basically. And I don't even think it's necessarily MobX-State-Tree. Specifically, it's more that Metro is leaving as undefined until it resolves all of the different things, and then it comes back and kind of re-adds that. So yes, this can be very frustrating. By the way, one of our priorities on the MobX-State-Tree core team is to improve error messages like this tremendously. So we're going to be putting a lot of effort into improving error messages so that they're not so like, what's going on here? But yes, that's a tough one and MobX-State-Tree has a way to work around this. You can pass in type style lazy, which basically waits until everything is done before it actually runs the type and then circular dependencies work fine because it now has what it needs and it can pass it in instead of this [crosstalk].
Robin Heinze:
Then the issue is when--it's kind of like a race condition, right?
Jamon Holmgren:
It is, yes.
Robin Heinze:
So if it's trying to load it in at compile time, so at the right time.
Jamon Holmgren:
It's not an asynchronous race condition, but it's more like...
Robin Heinze:
A file order.
Jamon Holmgren:
The first pass through, it's undefined, and then it comes through again and everything is now defined, and it can pass the references to the proper spots. But since you're building the MobX-State-Tree model, in the first pass, it doesn't have what it needs. So that's where lazy then allows it to run in the second pass. But yes, that can be a very frustrating thing. And what's funny is Mark posted it. I feel like Mark finds all these bugs for us. It's always Mark. But he posted this error and I looked at it and I saw what was happening. I immediately knew this has got to be a circular dependency because I've run into this so many times. And so, hey, just do that lazy type style lazy, and it'll fix it. He ended up actually finding a different way. I think he removed the thing that was causing the circular dependency. And then it...
Robin Heinze:
Yes. It's kind of the way we've been getting around this. This bug is just not importing this one thing from the problematic file.
Jamon Holmgren:
Type style lazy though, is really the way to go with that.
Robin Heinze:
Yeah. Type style lazy. It's also useful if for whatever reason you have a model that has a property of a certain type, and then you have that type also references the first type. So if you have a user model and each user has a list of friends, and then you have a friend model that has a list of [Crosstalk-23:55] or something like that, where you're importing two things from each other, type style lazy.
Jamon Holmgren:
There you go. Yes, because then it will wait on defining one of those relationships until both are defined. Very cool. All right. Where can people find you online to have you solve all of their debugging problems for them? Adhithi, where can people find you?
Adhithi Ravichandran:
They can find me at @adhithiravi on Twitter, and I think another strategy that works with debugging is if you're really stuck, you don't know what's going on, just walk away. Walk away, go for a walk, and drink some tea or whatever you like, and come back. And usually that really helps.
Jamon Holmgren:
That's a really good point. We should have mentioned that earlier. I totally agree. Sometimes just even sleeping on something--you sleep and your brain kind of sorts things out and you wake up with the answer in your mind.
Adhithi Ravichandran:
Absolutely.
Jamon Holmgren:
Robin, where can people find you on Twitter?
Robin Heinze:
I'm @robin_heinze with an E at the end.
Jamon Holmgren:
Perfect. I am @jamonholmgren and you can find our podcast Twitter @ReactNativeRdio because we had to cut one letter out, unfortunately. So we cut the A reckoning of radio, but without the A at the end there. And as always, thanks to our producer and editor, Todd Werth, our transcript and release coordinator, Jed [Jamon intentionally mispronounces Bartausky] Bartausky
[laughter]
Jamon Holmgren:
It's an inside joke, sorry. And our social media coordinator’s Missy Warren. Thanks to our sponsor, Infinite Red. Check us out at infinite.red/reactnative. Special thanks to all of you listening today. Make sure to subscribe on all of the major podcasting platforms. Actually, you really only need to subscribe on one, just find the one that you actually use. And you can see-you know what, actually...
Robin Heinze:
Wherever you get your podcasts.
Jamon Holmgren:
Go ahead and subscribe everywhere. We'll take the extra views. That's totally fine. It's good for our egos. But just find us React Native Radio, wherever you find your podcasts. See you next time.
Adhithi Ravichandran:
Bye.