Debug anything: Browser-based React apps
Tags: debug, react, cra, learn
Published: 2020-05-04 09:15:45

---
title: Debug anything: Browser-based React apps
published: true
description: Let's look at how to connect our debugger to a React app generated with Create React App. We'll see how to launch a browser from VS Code to inspect a remote, async API call. It's super-powerful and at the same time a surprisingly easy thing to do. So, no more excuses when it comes to debug you CRA and React apps.
tags: #debug #react #cra #learn
cover_image: https://www.datocms-assets.com/22772/1587457244-photo-1581276879432-15e50529f34b.jpg
series: Debug Anything
canonical_url: https://charlesagile.com/debug-create-react-app
---

# Code setup

To speed things up, I've prepared a simple React app we can play with here, so all you need to do is to check out [the repo for this series](https://github.com/thekarel/debug-anything) and start the CRA dev server:

```
git clone git@github.com:thekarel/debug-anything.git
cd debug-anything/react-cra
yarn # npm i
yarn start # npm start
```

You should see a successful launch message in your console:

```sh
Compiled successfully!

You can now view react-cra in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://192.168.0.4:3000

Note that the development build is not optimized.
To create a production build, use yarn build.
```

# Creating a `launch.json`

As discussed before, we need a `launch.json` for non-trivial use cases - see [Debug anything: launch.json & the debug console](https://charlesagile.com/vscode-launch-json-and-the-debug-console) for more details.

The sample code already contains the launch configuration too. It's pretty straightforward, but let's walk through it line by line, to make sure we understand what's happening. Open `.vscode/launch.json`:

![](https://www.datocms-assets.com/22772/1587457097-deuganything-05-01-launch-json.png)

Let's focus on lines 8 to 12 and go from top to bottom:

```json
{
    "type": "chrome",
    "request": "launch",
    "name": "Debug CRA web app in Chrome",
    "url": "http://localhost:3000",
    "webRoot": "${workspaceFolder}/react-cra"
}
```

`type`: this sets the debugger type to `chrome`, meaning we'll use Chrome browser in this config. Another type we've before used is `node` - there are many others you can get by installing extensions. There's one for [Firefox](https://marketplace.visualstudio.com/items?itemName=firefox-devtools.vscode-firefox-debug) too 🦊 

> Each debugger `type` has its specific configuration, so try to use the handy autocomplete that comes with VS Code.

`request`: the selected option `launch` means we'll launch a browser for debugging and it will load the address specified below. It's not very different from what you'd do manually, but Code automates it for you. Another possibility is to `attach` to an already running debug server, which is not possible here.  It's good to know that VS Code will take care of closing Chrome when you stop the debug session.

`name`: any name you prefer, this will show up in the debug toolbar:

![](https://www.datocms-assets.com/22772/1587457102-deuganything-05-02-name.png)

`url`: the URL the browser will load - **this has to match the one where the CRA dev server is running!** 

`webRoot`: the path to the project source files. *Source maps are not reliable in CRA development mode, unfortunately.*

# The CRA debug recipe

So how does all this hang together? The debug process is made up of the following steps.

First,  you start the dev server in a console with `npm start` - this can be done in VS Code too by the way.

![](https://www.datocms-assets.com/22772/1587457106-deuganything-05-03-start-script.png)

Next, you *launch* the debug browser from the debug sidebar, or by pressing `F5`:

![](https://www.datocms-assets.com/22772/1587457110-deuganything-05-04-start-browser.gif)

Add breakpoints to your code as usual:

![](https://www.datocms-assets.com/22772/1587457138-deuganything-05-05-breakpoints.png)

Then interact with the site in the debug browser, but this time with the debug powers enabled 💪 Let's see how a successful `fetch` looks like in our sample app:

![](https://www.datocms-assets.com/22772/1587457143-deuganything-05-06-success-debug.gif)

You can restart the session and bring the app back to its original state by using Restart in the toolbar:

![](https://www.datocms-assets.com/22772/1587457163-deuganything-05-07-restart-debug.gif)

You might be wondering if this is any better than opening the page in a "normal" Chrome and using the dev tools? The difference is not huge in this case. One clear benefit, though, is that you get to keep your breakpoints even after you close the browser or quit Code. This applies to watch expressions too! Speaking of which...
 
# Bonus: adding watch expressions

We've seen how to [inspect and even edit local variables](https://charlesagile.com/debug-anything-editing-variables-and-restarting-functions#hello-undefined). Going to the variables section and looking at values works. But if you're dealing with complex objects, repeatedly opening up nested structures gets annoying fast. 

VS Code offers a more comfortable solution: you can set *watch expressions* that will be re-evaluated in each debug step. It's even possible to query nested properties with the dot notation (e.g. `post.title`).

Make sure the **Watch** section is open in the debug sidebar and add a few expressions:

![](https://www.datocms-assets.com/22772/1587457180-deuganything-05-08-add-watch-expression.gif)

Let's try to fetch an existing post and keep an eye on the expressions:

![](https://www.datocms-assets.com/22772/1587457195-deuganything-05-09-watch-200.gif)

With these expressions, it's easy to inspect the unhappy path too - keep an eye on the `error` this time:

![](https://www.datocms-assets.com/22772/1587457222-deuganything-05-09-watch-404.gif)

As you might have guessed, the method we used above applies to any browser-based app. The setup is roughly the following in these cases:

* Start the development server
* Configure your `launch.json` to open the app in the debugging browser
* Set breakpoints in your source code
* Set watch expressions when you repeatedly inspect the same property
* Use [step commands](https://charlesagile.com/debug-javascript-typescript-debugger-navigating-with-steps) to inspect the code flow
* [Restart functions](https://charlesagile.com/debug-anything-editing-variables-and-restarting-functions#rewind) or the whole app