How to debug a React app
Tags: javascript, webdev, react, debug
Published: 2022-05-02 19:41:02

## Introduction

Since I started working as a software developer, I find myself spending the majority of the day debugging a big react app. This is not the result of a poorly implemented code, but what I feel is the natural process in which I find myself involved daily:
* I can debug to find the root cause of an actual **bug**
* Or I can debug as part of the normal **development process** (most likely)

<img width="100%" style="width:100%" src="https://media.giphy.com/media/10eJOwQ9BKrF72/giphy.gif">

When hunting for actual bugs in the code, we need to focus on tools and systematic processes to analyse the code in search of what's not working and accept the fact that the person that wrote the code may not be available to answer our questions. Sometimes, though, the bug might have been introduced by ourselves 🙋‍♂️, and we can find it difficult to step in the shoes of our past selves in order to understand why we did what we did. No matter what's the case, they all have something in common: we need to use tools to help us debug the app and find what's wrong with it.

More often than not, I feel debugging is not solving a particular issue affecting a customer, but the natural process inherent to the development of software. If I want to create a feature for an existing app (or build one from scratch), I will often face code that is not working as it is supposed to 🤷‍♂️, and here is when I will pull out the "debugging arsenal" to find out what's wrong with the code in order to keep moving forward in the development process.

### A special note: when a bug is introduced by ourselves

Let's apply some logic here: 🤔 if **we have created a bug**, then **we are not in the position to be able to solve it**, because if we could, we wouldn't have created it in the first place! This is why we need additional tools that can help us to step outside ourselves in the process of finding a bug, just like if we were detectives trying to solve a crime in which we are the prime suspect. We need to be methodical, go step by step, test a lot, and gather evidence. Here is where debugging tools come to our rescue.

## Breakpoints and the `debugger`

When debugging a React app, I often find breakpoints to be very helpful. There are two main ways in which we can use them:
* By writing the `debugger` statement in our source code
* By clicking on a specific line of the code in the Chrome web browser (or Firefox, Edge, etc.) Developer Tools.

### Using the `debugger` statement

> The debugger statement invokes any available debugging functionality, such as setting a breakpoint. If no debugging functionality is available, this statement has no effect. - [Source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger)

Let's say we have a project in which we are interested in finding out what's happening in a particular section of code. In this example, I'm using the source code of my portfolio site, which you can find in [this GitHub repository](https://github.com/Colo-Codes/portfolio-v2)). I have introduced a bug, and now I will search for it using the debugger.

In this particular bug, the third animation related to the portfolio title is not working correctly, so I can write the `debugger` statement in that section of the code.

![Hunting a bug](https://cdn.hashnode.com/res/hashnode/image/upload/v1650856471474/yD4jsNY4D.png)

Once the file is saved and compiled, as soon as I reload the page and the browser parses that code, it will stop on the line that has the `debugger` statement on it. The browser will then display useful data in the Developer Tools pane.

![Developer Tools](https://cdn.hashnode.com/res/hashnode/image/upload/v1650856488132/Og9HWSBcs.png)

We can see the value of variables at that moment by **hovering** over them in the source code, or in the panel located on the right, in the **Scope** section. Thanks to this, I can see that the value of the `setIsAnimated1` function is being called with the wrong value.

### Using breakpoints

Breakpoints work in a very similar way. To enable breakpoints we need to open our site in a web browser (I'm using Chrome in this case) and open the **Developer Tools**. Now, if we click in the **Sources** tab and in the tab with the **file name** that we are interested in debugging, we will see our source code once more, as happened in the previous method using `debugger`.

> Note: for more information about the **Developer Tools**' **Source** tab, read [this article](https://developer.chrome.com/docs/devtools/javascript/).

![Using breakpoints](https://cdn.hashnode.com/res/hashnode/image/upload/v1650856786675/i5YnhjWbG.png)

Now, in order to create a breakpoint, we can click on the margin just next to the line number. These breakpoints will be listed in the panel shown on the right, in the **Breakpoints** section. We can now reload the page, and the loading of it will stop at the breakpoints we have set (we can click the play button to tell the browser that it should continue executing the code and, thus, loading the page).

If you want to learn more about this topic, and even set **conditional breakpoints** or **stop the code execution when a node is removed**, for example, I think you should read the [Pause your code with breakpoints](https://developer.chrome.com/docs/devtools/javascript/breakpoints/) article.

## React Developer Tools

The previous debugging tools apply not only to React apps but to any JavaScript app. But, when working with React apps in specific, we have a very useful tool: the **React Developer Tools** browser extension. You can find this extension by searching for it on the corresponding browser extension marketplace. For example, for Chrome, you can install it from [this link](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi).

The react Developer Tools is a set of two main tools:
* the **Components** tool, where you can analyse the structure of the components,
* and the **Profiler** tool, where you can see the time each component took to render and how they are updated.

### The Components tab

In the Components tab, you will be able to see the component structure of the site you are analysing (left panel), as well as the `props`, `hooks` (for function components) or `state` (for class components) that a selected component has (right panel), together with a list of the ancestors that ended up rendering the component you have selected.

![Components](https://cdn.hashnode.com/res/hashnode/image/upload/v1651387233982/1SZvzsci2.png)

Just by the information this tool is presenting I think it's very valuable, but that's not all! You can also modify the `props` and `hooks` of the component you have selected, and this will affect the site in real-time, something that's very useful for debugging purposes. 🤯

![Modifying a component](https://cdn.hashnode.com/res/hashnode/image/upload/v1651387895341/rOl0YE0Yo.png)

### The Profiler tab

As mentioned earlier, we can use the Profiler to record the time it took each component to be rendered. In order to do so, we need to click the `Start profiling` or `Reload and start profiling` buttons.

![Profiler](https://cdn.hashnode.com/res/hashnode/image/upload/v1651388146779/us3oTSNOg.png)

Once the site has been rendered, we'll need to click the `Stop profiling` button, and we will see a graph detailing the time each of the components took to be rendered. Instead of clicking on the `Stop profiling` button, we can interact with the site, clicking on buttons, menus, etc., and the profiler will record these interactions at a component level.

![Profiler record](https://cdn.hashnode.com/res/hashnode/image/upload/v1651388376024/1mCiEIBT7.png)

This is very helpful when we need to debug certain interactions with our app.

### Bonus: check why a component was rendered

If we are interested in knowing why a particular component was rendered, we can activate this feature by clicking on the **gear icon**, then in the **Profiler tab**, and finally ticking the `Record why each component rendered while profiling.` checkbox. 

![Extra options](https://cdn.hashnode.com/res/hashnode/image/upload/v1651388506920/mt3uyiIFx.png)

Now we need to start a new profiling, just as before, and we'll be able to see extra information concerning the reasons why a component was rendered. Some of the most common reasons for a component to (re)render are, as you can see by using this tool:
* the parent component was rendered
* its `props` changed
* its state-related `hooks` changed

![Re-renders](https://cdn.hashnode.com/res/hashnode/image/upload/v1651388748200/TsdPOp0gY.png)

I have found that recording why a component was rendered saved me many headaches when debugging a complex React app.

## Workflow debugging

There are some occasions in which none of the previously mentioned tools can help us to find a bug. In this case, I like to use a "workflow debugging" approach. This method consists in start analysing the code in the closest region to where the bug is happening, and following the flow of the code "upstream": which method is creating this section of code, what's its parent, grand-parent, etc.

Let's say a header in our app has a wrong margin. We can start by analysing the code closest to this header, looking for methods that can be altering its margin, and then analysing the code that's affecting the header at higher levels, like an inverse [Matryoshka doll](https://en.wikipedia.org/wiki/Matryoshka_doll).

![Matryoshka doll](https://cdn.hashnode.com/res/hashnode/image/upload/v1651389275457/t8kbBo3Im.png)
*Photo by Didssph on Unsplash*

## The debugging methodical process

In order to be consistent in how we proceed to find a bug, we can create our own process or framework by combining these tools and approaches. For example, when facing a bug we could:
1. Start by analysing the workflow the code is following that affects a particular section of code.
2. If nothing wrong is found, we could use the React  Developer Tools to analyse each component closely.
3. If that analysis is not delivering results, we could apply breakpoints at different sections in the code and see how the variables are being altered.
4. If everything else fails, just comment out pieces of code and see what happens. Experiment.

## Conclusion

We have many  tools at our disposal to look for bugs, but it's not always easy to find them. I think it's very important not to feel frustrated when debugging an app, and to focus on a systematic, step by step process to analyse the code.

I'm sure I haven't covered all the techniques available for debugging a React app, so if you have one that's your favourite and that is not listed here, please share it in the comments so we can all learn from it. 😊

---

🗞️ **NEWSLETTER -** _If you want to hear about my latest articles and interesting software development content, [subscribe to my newsletter](https://mailchi.mp/22b236f812b1/subscribe-to-newsletter)._

🐦 **TWITTER -** *Follow me on [Twitter](https://twitter.com/DamianDemasi).*

<a href="https://www.buymeacoffee.com/damiandemasi" target="_blank"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641530738382/Wt_2bHGsXK.png" alt="Buy Me A Coffee" style="height: 40px !important;"></a>