How to debug ReactJS applications

Mehdi Osman
Feb 27 · 10 min read

Knowing how to effectively debug an application is of the utmost importance to frontend developers as they’ll be spending a good portion of their time reproducing and fixing issues. Besides, what better way of deeply understanding a language or framework if not by looking at its inner workings.

In this article, we’ll be covering some of the tactics and tools ReactJS programmers use on a daily basis, not only in their very predictable development environment, but also in production when their code comes to life and things may — and will — go haywire.

(Most of the learnings here are applicable to all frontend applications)

React debugging tools

One of the popular extension out there is definitely the React Developer Tools available on both Firefox and Chrome. It makes it easy to inspect and edit the props/state of the root React components rendered on the page and record performance information.

But the best debugging tools are already bundled with your browser. The good old “inspector” will boost your productivity when it comes to debugging JavaScript, tweaking DOM and CSS, inspecting network activity, analyzing performance, tracking down memory leaks and much more.

How to debug with Chrome DevTools

Let’s hit F12 and get familiar with the different panels.


The Console serves two objectives at least: display of your application’s logs plus runtime errors and ability to execute custom JS code.

Developers may be logging messages using console.log() to inspect the value of some variable or simply ensure their code is executing in the right order. Warnings and majority of runtime errors get also printed here. See console JS object to learn what you can do it with it.

On top of that, your Console is a REPL environment and has full access to window. In other words, you can use it to run custom JavaScript code that interacts with your React application. More about the Console Utilities API here.

Network Panel

This where your entire application’s network activity will be logged. All resources, whether downloaded or uploaded, are available for inspection in the Network panel. These resources are listed chronologically with information such as HTTP response code, loading time, initiator, state and size. The footer contains a summary of the total number of requests and the size of all resources.

This list view helps easily spot requests that failed (the red ones) and those that are pending and may soon timeout. If you’re looking for CORS issues, it’s better to start from Console then eventually switch to Network (these requests appear in white, as successful).

Clicking on a specific resource opens a detailed panel where HTTP Headers are shown, alongside the Response and even an HTML Preview of it. It’s in fact easier to debug the received data or simply inspect images here than in your HTML source code.

And finally the Timing breakdown which can prove very useful when investigating requests that take a long time to download, either due to a poor connection between your React application and the server (consider using a CDN if Time To First Byte is high) or to a slow backend if that server is hosted locally.

Tips: Hit Preserve log to keep the logs when navigating from one page to another, and check Disable cache so resources won’t be served from cache when DevTools is open.

JS Debugger

This is by far the most powerful tool available in DevTools, and you can find it under the Sources tab.


This a faster and cleaner alternative to using console.log() when looking for bugs. It allows for quick inspection of the piece of code being executed and the values of all variables at that moment in time.

The execution comes to a halt as soon as it reaches the breakpoint. And you can set many of them at the same time. From there you can deep dive into your code using the different options at hand:

  • Step through the code by resuming execution, one line at a time, or hop on to the next function call.

Other types of breakpoints are available:

  • DOM when a node or its children gets changed or removed.

Run Snippets

From the same Sources panel, you can save your repetitive code into Snippets. They have access to your JavaScript context and can be run anywhere in your application.

Local Overrides

Who doesn’t hate losing changes whenever you hit that reload button? Local Overrides were made to overcome this. Specify a directory in Sources -> Overrides and let DevTools save your changes. It works in most situations (see limitations).

Store Specific Tools

DevTools might not be enough whenever you need to deep dive into some specific issues related to your store. Here are some of the tools you may use for Redux and MobX.


  • redux-logger — for keeping track of your redux actions and state changes.


  • mobx-logger — for logging actions, reactions, transactions and computations.

HTML Structure & CSS

The Element tab is where you do all your DOM related activities. It allows you to edit the DOM and CSS on the fly.

Inspect DOM

You can inspect any particular DOM node, change its content, attribute or type and force its state (like :hover). You can remove nodes or reorder your tree by drag and dropping them and see how it renders.

DevTools lets you also use nodes in Console and even store them as global variables in case you need to refer back to them. But perhaps the most useful trick is to pause your JavaScript whenever it tries to update a DOM node. You can do that by adding a break on attribute change, node removal or subtree modification.

Edit Styles

On the right side of the panel you can see the CSS styles that are applied to the selected DOM element. DevTools lets you inspect styles in different ways by editing them, or by adding new styles and rules. The box at the bottom helps with the margins, paddings, dimensions and border.

Make sure to persist your changes to the development workspace if you don’t want them to disappear upon the next reload.

Performance Audit

DevTools offers several ways (across various panels) to audit and improve the performance of your React application.

Loading Speed

The Audits tab is where you can look for bottlenecks hurting your page’s loading speed. Open your application in incognito mode as some browser plugins may interfere with the auditing workflow.

Start with an audit as it creates a baseline to measure your changes against, but also gives your some actionable tips on how to improve. The available options let you run different categories of audits: SEO, accessibility or performance oriented. It also helps simulate how your application behaves on a mobile device (viewport and bandwidth/CPU throttling).

Results show the overral score (the higher the better) and a set of different sections:

  • Metrics — laying out the different aspects of the loading experience, such as when the content is displayed (First Contentful Paint) or when page is ready for user interactions (Time To Interactive).

Tip: Isolate your changes by making one improvement at a time, before rerunning an audit for measuring how it affected performance.

Memory Leaks

Memory issues are obvious and often times noticed by your users as your application will tend to either pause (GarbageCollector kicks in more frequently than it should) or becomes slower throughout the session (think memory leak).

A dedicated Memory tab helps investigate these issues. Track down memory leaks by monitoring your JS heap (in Allocation timelines) and by finding detached DOM nodes — those removed from the tree but still being referenced by some JS — using Heap snapshots. You can even dissect memory allocation by function.

Learn more about this topic here.

CPU Profiler

You can record a JavaScript CPU profile and examine the functions that have impact on your application’s performance. Results can be shown in 3 ways: top-down (tree), by impact(heavy) or chronologically (flame chart).

Frames per second

FPS is captured alongside other metrics by DevTools at execution time. It is useful for spotting slow animations that hurt your user experience. Low framerates translate in red bars on the chart.

DevTools also offers an FPS meter, producing real-time estimations at runtime, and CPU throttling for simulation on mobile devices.

How to debug Production issues?

Issues reported by users do often lack the full context to have a complete understanding of what happened. “X doesn’t work” doesn’t obviously help you. Not to mention the time it takes to collect clues from your users with the hope of being able to reproduce the problem locally. Besides, how many of them would bother to submit a ticket or share a bad experience? An extremely tiny fraction I guess.

So don’t go easy on logs. Anything that helps you make sense of a bug is useful. Below are a few tips on what’s worth tracking.

Monitor your XHR

Make sure to log the XHR requests that failed (5xx/4xx) and their responses. Most HTTP libraries will allow to easily handle such cases.

Catch your JS errors

Runtime errors are critical for diagnosing issues. They are worth a thousand log entries and provide an accurate picture of the problem. Store them on your server for later retrieval. If you had to log only one thing, start with JS errors.

Track your app’s State and Actions

Whether using Redux, MobX or any other store, take the time to log your application’s state changes and actions. You can even replay them in your browser, if you’re on Redux, with redux-slider-monitor. This would come in handy for thorough debugging of production issues.

Record your user actions

Logging user actions and journeys is a powerful, yet underused technique in debugging. Such strategy is widely used by marketers who track down each and every frustration that may affect the overall user experience, ranging from rage clicks to incorrect rendering of certain elements in the web app. Tools like Mixpanel, Amplitude or Heap haven’t been designed for developers and therefore rarely used by them. But this is not an excuse for not simply logging your user steps after sanitizing any residual private data.

In fact, being able to mentally visualize your user journey — while they experience an issue in production — and at the same time see how that affected your React stack is simply HUGE. It’s the ultimate root cause analysis technique and a serious productivity booster.

Monitor React apps in Production

Debugging a React application in production may be challenging and time consuming. Try using a unified monitoring platform that gathers all you need for troubleshooting in one single place. Try Asayer for free.

Asayer is a frontend monitoring tool that replays everything your users do and shows how your React app behaves for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder.

Asayer lets you reproduce issues, aggregate JS errors and monitor your app’s performance. Asayer offers plugins for capturing the state and actions of your Redux/MobX stores and for inspecting GraphQL queries.

Happy debugging, for modern frontend teams - Start monitoring your React app for free.


Asayer is a frontend monitoring tool that helps developers…

Mehdi Osman

Written by

Founder & CEO @ Asayer (



Asayer is a frontend monitoring tool that helps developers reproduce bugs, aggregate errors and improve performance.

More From Medium

More from Asayer

More on Redux from Asayer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade