DEV Community

Cover image for How To Debug React Apps With VS Code - Boost Your Debugging Productivity
Johannes Kettmann for Profy.dev

Posted on • Originally published at profy.dev

How To Debug React Apps With VS Code - Boost Your Debugging Productivity

Debugging a React app can be a slow and painful process. Adding a console.log() statement here and there until you’re finally in the right spot. Or a more advanced version: Jumping around between setting breakpoints in the Chrome dev tools and editing code in your IDE until the bug is fixed.

But with the right tools and a strategic approach debugging can become much easier. Maybe even fun?!

Turns out much beloved VS Code makes it very simple to debug a React app directly from the IDE. The result: Super easy setup and a more productive debugging workflow.

On this page, you can see how to set up VS Code as a debugger for your React app and see it in action. We’ll debug a small problem with a Next.js application and use (conditional) breakpoints, step into functions, and inspect and edit variables directly from the VS Code. All of this paired with a structured debugging approach and the bug is fixed in no time.

Here’s a short video showing how to set up and use the VS Code debugger. Alternatively, you can find a detailed step-by-step tutorial with screenshots on this page.

Click here to get the source code for this tutorial

Table Of Contents

  1. Launch Chrome via VS Code
  2. Using The VS Code Debugger
  3. The VS Code Debugger In Action
    1. Using Breakpoints in VS Code
    2. Conditional Breakpoints To The Rescue
    3. Finding The Root Cause
    4. Inspect And Edit Variables In The Debugger
    5. Step Into A Function

Launch Chrome via VS Code

Starting to debug your React app with the VS Code debugger is surprisingly simple. You let VS Code create a launch.json config for you and slightly adjust it. You can find the file in the .vsocde folder in your repository.

Depending on your app you need to

  • adjust the url field (here I change the port to 3000)
  • adjust the webRoot entry (e.g. if your code is in the src folder like create-react-app apps you change ${workspaceFolder} to ${workspaceFolder}/src)

react-debug-vscode-setup-launch-config.gif

Now you can hit the play button ▶️ to start a Chrome browser in debug mode. The VS Code debugger is automatically attached to this browser.

Note: You could run Chrome in debug mode manually and use the “attach” launch config to attach the VS Code debugger. But I don’t see a reason to overcomplicate things.

If you already have a launch.json file or want to add another config to it you can simply use Intellisense (e.g. by pressing cmd + space on Mac) and get suggestions.

react-debug-vscode-add-config-with-intellisense.png

Here is my launch.json file:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Run Chrome",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000",
      "webRoot": "${workspaceFolder}"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Using The VS Code Debugger

Two use the debugger you need two things:

  1. Run your React app (e.g. by running npm start).
  2. Start Chrome via VS Code by pressing the play button ▶️.

You can now use the debugger as you would in the Chrome dev tools. If you’re not familiar with that you can see an example below.

The VS Code Debugger In Action

Let’s imagine the following situation: We’re a developer working on a Next.js app that is in production. Real users, nothing should break.

One of the most important pages used to look like this (you can see a deployed version of it here):

react-debug-vscode-website-without-bug.png

But suddenly we get reports that something is broken (here a deployed version):

react-debug-vscode-website-production-error.png

Damn, how did this bug make it into production? Our customers are upset. They’re paying good money and rely on our app. Obviously, our managers are going crazy as well.

But we as the developers stay calm. With the right debugging approach we can probably fix this bug in no time.

The error message in production doesn’t tell us a lot. So first we run the app on our local machine.

Click here to get the source code for this tutorial

Since we know that we need to debug the code we use the VS Code debugger to start a Chrome instance.

react-debug-vscode-run-chrome-in-debugging-mode.png

This opens the browser at localhost:3000 as defined in launch.json.

Now when we navigate to the problematic page we see this error.

react-debug-vscode-error-on-local-machine.png

Using Breakpoints in VS Code

This error is much better than what we see on the production website. It provides us with two important pieces of information:

  1. The error message “Cannot read properties of null”.
  2. The name of the file and the line where the error occurred: line 49 in issue-row.tsx.

Opening the file in VS Code is really simple. The file path in the error message is in fact a link:

react-debug-vscode-open-file-by-click-on-error-message.png

When we click it, the file issue-row.tsx opens in VS Code. Magic.

The error message tells us that the issue prop is likely null at some point. Let’s verify that by adding a breakpoint. Simply click inside the empty space next to the line number.

react-debug-vscode-set-breakpoint-and-restart.png

Once you press the green “Restart” button ↻ the page refreshes.

To speed up the process you can also use a key combination (Cmd + Shift + F5 in my case). You can hover over the button to find out yours.

The code execution stops at the breakpoint. At the same time, the website freezes in its loading state.

react-debug-vscode-code-execution-stops-at-breakpoint.png

As you can see in the screenshot above the issue prop is defined during the first render.

So we press the “Continue” button ⏯️ or F5 a couple of times. The problem is that there are quite a few IssueRow components being rendered. So hitting “Continue” until we find the right issue becomes quickly annoying.

Conditional Breakpoints To The Rescue

Instead of hitting “Continue” all the time, we’d like to skip all the issues that are defined and only stop at the nullish one.

The easiest way to do that is by adding a condition to the breakpoint. Right-click on the breakpoint and select “Edit Breakpoint”.

react-debug-vscode-edit-conditional-breakpoint.png

Now we can enter a JavaScript expression. In our case, we want to stop at issue === null.

react-debug-vscode-add-expression-to-conditional-breakpoint.png

We hit enter and continue code execution. And voila we can confirm that at least one issue is null.

react-debug-vscode-inspect-variables.png

To be honest, this isn’t exactly news to us as we already knew this from the error message. But at least we were able to confirm the problem.

Finding The Root Cause

So let’s dig a bit deeper. In a simple JavaScript program, we could just follow the call stack or press the “Step Out” button (⬆️) to find the root cause of the problem.

But with React (and other frameworks) it’s not that easy:

react-debug-vscode-callstack-react-internal-files.png

Except the IssueRow we can’t see any of our code files in the “Call Stack” panel. Everything else is internal React files.

This doesn’t help us much.

So, unfortunately, we need to find out where the IssueRow component is rendered manually. The global search function of VS Code is our best friend here.

react-debug-vscode-global-search.png

We open the file and add another breakpoint just before the return statement of the component.

Then hit the refresh button ↻ in the debug controls or F5.

react-debug-vscode-inspect-variables-array.png

Great, now we see that one item in the items array is indeed null.

Inspect And Edit Variables In The Debugger

Our assumption is that this null value causes the bug. But before we start messing around with our code we can easily verify this assumption by editing the variable inside the debugger.

react-debug-vscode-edit-variable-in-debugger.gif

When we continue the code execution now we can see that the error disappears on the website. The 7th and 8th items in the issue list are now duplicates as expected.

react-debug-vscode-verify-fix.png

This verifies our assumption that the null value in the data array is the problem.

That makes the solution to our bug simple: we can just filter out all null values from the data to fix the bug. Of course, we could implement the filter function in the component. But maybe a place closer to the data source would be more suitable. This way other (future) components could potentially benefit from the same fix.

Step Into A Function

To dig a bit deeper we have a look at the beginning of the component. The items array with the null value comes from the issuePage variable. And that one comes from a hook.

So let’s set another breakpoint there and hit the refresh button again. Code execution stops at the breakpoint.

react-debug-vscode-step-into-hook.png

Now we can use the “Step Into” button ⬇️ to investigate that hook. The first file that opens is again some internal React file.

react-debug-vscode-step-into-hook-react-internal-file.png

But this time we’re better off. After hitting the “Step Into” button a couple of times we end up in the useIssues hook.

Having a closer look the getIssues function seems like a good candidate to filter the data.

react-debug-vscode-fix-1.png

Unfortunately, for some reason, we neither can step into the getIssues function nor does code execution stop at a breakpoint inside. If you have a bit of debugging experience you know that there are inconveniences like this from time to time.

Anyway, let’s not allow that to hold us back. We add a bit of code to filter the issues.

react-debug-vscode-fix-2.png

Once we hit return we can confirm that the bug is fixed.

Commit, push, deploy. Everyone’s happy.

Click here to get the source code for this tutorial

Latest comments (13)

Collapse
 
lizardkinglk profile image
sndp • Edited

Nice post. Thanks for sharing.

Collapse
 
bgw8 profile image
Emil Rydén

When i signup and get the invitation for the repo it seems like the code/url in the instructions are the already fixed one, as there's no bug showing for me when navigating to the "issues" tab. Any ideas?

Collapse
 
jkettmann profile image
Johannes Kettmann

You need to check out the branch "debugging-exercise" :)

Thanks for that question btw. I added that info to the email but didn't realize that the code formatting was broken. Wouldn't have found out without your comment

Collapse
 
bgw8 profile image
Emil Rydén

Thank you Johannes, forgot to check the remote branches and thought it was stuck on "main" :)

Collapse
 
katya_pavlopoulos profile image
Katya Pavlopoulos

The kind of React debugging tutorial I've been looking for! Thank you so much Johannes!

Collapse
 
medimess profile image
Mehdi Messarat

Thank you very much, very helpful post

Collapse
 
jkettmann profile image
Johannes Kettmann

Thanks for the feedback :)

Collapse
 
olsard profile image
olsard

Great! Thanks a lot for so nice explanation!

Collapse
 
jkettmann profile image
Johannes Kettmann

Thanks for the feedback :)

Collapse
 
liago profile image
Liago

Cool! Finally someone that explain in a clear way. Thanks a bunch, mate!

Collapse
 
jkettmann profile image
Johannes Kettmann

Thanks for the feedback :)

Collapse
 
devangtomar profile image
Devang Tomar

That was a nice read! Liked, bookmarked and followed, keep the good work! 🙌

Collapse
 
jkettmann profile image
Johannes Kettmann

Thanks a lot for the nice words :)