Debugging in a React Application

Posted by Saurabh Misra on October 4, 2016 in ReactJS

I recently started learning and using React and I am fascinated with the coding flexibility it brings to the table for developers.

In this article, I am going to outline some of the tools and techniques that will help developers easily and quickly debug errors in their application. This article assumes you have some basic knowledge about React. If you don’t, check the React official docs here and get started. I will also be using ES6 Javascript syntax. If you want to learn more about the new ES6 additions, you can check them out here.

Helpful React Error messages (Development version)

React is all about providing a better developer experience and one of the ways it does this best is by providing helpful error messages that not only state what went wrong, but also what might have caused it and what you can do to rectify it.

Lets consider a very simple example of an erroneous component using the React Starter Kit.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Helpful Error Messages in React</title>
    <script src="build/react.min.js"></script>
    <script src="build/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-core@5.8.38/browser.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      var App = (props) => {};

      ReactDOM.render(
        <App/>,
        document.getElementById('app')
      );
    </script>
  </body>
</html>

As you might have figured out, our simple component returns an empty object which is not a ReactElement. Lets see how React informs us about this error. If you run this, you will see the following error in your console.

Uncaught Invariant Violation: App.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.

Isn’t that just awesome! We can instantly figure out that the error is in the App.render() method, and is occurring because our code is not returning a valid ReactElement.

Error Code System (Production version)

Please note that the descriptive error messages in the above example are available in the uncompressed development version of React. In the production version, these messages are stripped. So if we would have used the minified versions of react and react-dom available in the starter kit, the error message would have read something like this.

Error: Minified React error #105; visit http://facebook.github.io/react/docs/error-decoder.html?invariant=105&args[]=App for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

If you visit the link, you will see the same descriptive error message that was shown while using the development version. This is made possible by the Error code system that associates an ID with invariant errors and provides a link in the error message which decodes the ID and maps it back to the descriptive error message. Click here to know more about the Error Code system.

React Developer Tools

By far, the best React debugging tool is the React Developer Tools which are available in the form of browser extensions/add-ons. You can download them from the these links:

React Dev tools for Chrome

React Dev Tools for Firefox

These dev tools basically create a Component Tree representation of your React app similar to the DOM tree. You can change props and state on the fly and see their effects on your webpage and a whole bunch of other stuff. You can find more information here.

Linting

Linting is a process where a program parses our code and informs us of any errors or if it does not adhere to coding standards. Linting can save developers a lot of time by detecting potential issues right in their editor or maybe in the console during the build step. For example, in the case of the above issue, wouldn’t it be cool if our editor flashed an error message saying that ‘ReactDom is not defined’ instead of us trying to debug the cause of the issue in the browser after the build succeeds and the app reloads. Lets try to do something similar.

Read this amazing article to enable linting in the code editor of your choice. I use Sublime Text 3 but these configurations should also work for others. Please make sure you install eslint-plugin-react and include their recommended presets.

Congratulations! You have just given your code editor superpowers.

Let us consider the example of a simple component for testing our linting configuration. I have chosen a more React specific error this time.

//Homer.js
var React = require('react');

var Homer = React.createClass({ 
  render: function() {
    <h1>D'OH!</h1>
  }
});

export default Homer;

In a state of coding frenzy, I have forgotten the return keyword in the render method. But fortunately I have linting enabled to point out my mistake before I begin building my code or refresh the browser.

linting

As you can see in the screenshot, Sublime highlights some of the code in red and displays an error at the bottom of the window that says:

Error: Your render method should have return statement (react/require-render-return) Line 3, Column 33

Woo Hoo!!

Linting in create-react-app

If you are using create-react-app, linting is already handled for you and error and warning messages are displayed in the console window after you run npm start and then whenever you make changes to your files and the build happens automatically. In our case, the same warning for the above issue is displayed in the console window where create-react-app is running. See screenshot below.

linting-in-create-react-app

But if you still need these messages to appear in your code editor, make sure you follow these steps.

Sourcemaps

After using a bundler like Browserify or Webpack, our entire source code gets bundled up into a single JS file. This can make debugging errors in a browser’s dev tools difficult as the error appears as a part of our bundled JS file and does not indicate in which component it has actually occurred. Sourcemaps enable us to map our bundled code back to original development code.

Lets consider a more complete setup this time. I will first use a simple build process based on npm and gulp that uses Browserify to bundle a simple but erroneous React Component and then with a similar setup, I will also explain how create-react-app handles sourcemaps out-of-the-box and makes debugging super easy.

You can download the npm/gulp based sourcemap tutorial source code here. Run npm install to install the dependencies. Then run npm run build-wo-srcmps to build without sourcemaps followed by npm run serve. You should now be able to access this at localhost:3000.

You will notice we have 3 JS scripts, index.js, App.js and Homer.js. Although we don’t need 3 scripts to generate 1 simple error but I have intentionally chosen this setup as it is similar to the way create-react-app organizes files. This way, it will be easier to explain the same error later with an actual create-react-app based setup.

Our App.js file contains a stateless component called App and looks like this.

//App.js

import React from 'react';
var App = (props) => <Homer/>
export default App;

You must have already identified the error here. I have forgotten to import the Homer component. But lets pretend that we are unaware of this error and see how we can debug this first without using sourcemaps. Access localhost:3000 and open your browser’s console, you will notice an error in our bundle.js script. See screenshot below.

sourcemaps1

As you can see, the error appears as a part of our bundle.js instead of App.js.

sourcemaps2

In this particular case, we can quickly figure out that the error is in App.js but imagine if you were working on a full blown application with hundreds of components. Diagnosing a similar error could indeed become really difficult and tedious.

Don’t fret, Sourcemaps to the rescue!

On your console window, run npm run build-w-srcmps followed by npm run serve. Again, access localhost:3000 and see your browser dev tools console. You should see the error associated with src/App.js instead of bundle.js.

sourcemaps3

If you click on it, you will see the original App.js file with your error in the actual line it occurs in your dev code.

sourcemaps4

What’s more! You can even set breakpoints in your sourcemapped JS scripts and your browser will pause on those breakpoints.

sourcemaps5

If you open package.json and see the command for build-w-srcmps and build-wo-srcmps, you will notice that the only difference is the -d flag which sets the debugging option to true.

You can also do this using gulp. Running gulp in your console will build without sourcemaps and initiate a server at localhost:3000. You will see the error associated with the bundled file. Now to generate sourcemaps, make a simple change to our gulpfile.js. In the options object that is passed to browserify(), set debug:true instead of debug:false. Run gulp in your console once again. View the error in your browser console and you should be able to see the error in src/Apps.js instead of bundle.js.

Sourcemaps in create-react-app

If you are using create-react-app for development, then you won’t really need to generate sourcemaps explicitly for development builds because create-react-app will take care of this for you. Use the same index.js, App.js and Homer.js from the source code provided above. When you run npm start, It will show you warnings for this error in the Command window as well as in the browser console. See screenshots below.

sourcemaps2

sourcemaps1

The warnings and errors are already associated with the original files.

For production builds, create-react-app will automatically generate sourcemap files when you run npm run build.

If you now include the below import statement in App.js and then build and serve, you will be able to get rid of the error.

import Homer from './Homer';

I hope this article and the tools and techniques mentioned here will help you be more productive in your React development. Let me know if I have missed something or if you would like to discuss something in the comments below.

Saurabh Misra

Saurabh Misra

Co-Founder of CodeSphere Solutions

Saurabh is a Web Development enthusiast. In his free time he likes to play his guitar, watch movies and explore the world.

We at CodeSphere Solutions specialize in Web development. Do you have a web development project you need help with?

Tell us about it
Share This