p3-insta485-clientside

React/JS Debugging Tutorial

This tutorial will walk you through how to debug Javascript with browser tools and debug React code with React Dev Tools.

Finish React Setup

To follow along with this tutorial, make sure you have finished the React setup first as described in the React/JS section.

JavaScript Debugger

The following tutorials discuss how to use browser tools to debug plain JavaScript without having to add console.log() statements everywhere. Be sure to read the tutorial for your preferred browser, as this will help you understand the React Dev Tools much better. We recommend Chrome (or similar like Brave or Chromium) or Firefox because they also support the newer React Dev Tools Extension.

Chrome

Get Started with Debugging JavaScript in Chrome DevTools

Firefox

Debugger

Safari

Debugging overview

Remember that static pages and server-side dynamic pages tools still apply!

React Debugger

Debugging React code can be tricky if you try to apply the JavaScript debugging tools on the JavaScript code that was transpiled from your React code. Instead, we can use the React Dev Tools browser extension, which allows you to view your React components as HTML DOM elements in the Developer Tools and see the props and state for each component. In the following section, we will walk through how to debug code for the Post widget you created in the React setup.

First, add React Developer Tools to Chrome or Firefox.

Verify that you’ve done the setup tutorial correctly. Build, run and navigate to http://localhost:8000/, where you should see your post widget with the text “awdeorio” after logging in.

$ pwd
/Users/awdeorio/src/eecs485/p3-insta485-clientside
$ npx webpack
...
$ ./bin/insta485run
...

For the purpose of this tutorial, let’s say there is a bug somewhere in your React code that is causing “owner awdeorio” to be displayed instead of just “awdeorio”.

Open up the browser’s developer tools, click on the arrow to see more tabs, and click on the Components tab, and click on the Post component. You should see the Post component with its props and state. You can also inspect the matching DOM element by clicking on the eye icon. As you can see, the state of owner is awdeorio as expected, so most likely the bug is introduced when the component is being rendered.

To view the source code associated with a particular component, click on the “View source for this element” button in the top right corner (looks like < >). You should now see the React code associated with the Post component in a relatively readable format unlike your bundle.js.

Since we think the bug is being introduced in the render() call, let’s set a breakpoint there, and add the variables of interest (owner and this.state.owner) to the watch section, and refresh the page. You should see that the page is not fully loaded and the execution stopped on your breakpoint. Note that the this.state.owner is empty because the component has not yet mounted. So click on the “Resume script execution” button to stop the execution again after componentDidMount() has completed. Now notice that this.state.owner is awdeorio.

Since the we are using the local variable owner in our render call to display the owner of the post, the bug most likely involves owner. As you step through the lines of code, you notice that you are rendering the string "owner " and the variable owner instead of just the variable owner. This is why owner appeared on the screen before the state was updated with awdeorio. You have now caught your bug!

Debugging React code is not as simple as debugging single-threaded C++ programs in an IDE because of the asynchronous nature of JavaScript. Make sure you understand what part of the execution you are in (after constructor() ran, before componentDidMount() ran, etc.) as that will help you diagnose the root cause of bugs much faster.

Building Sourcemaps

When following the React Debugger tutorial, you may have noticed that the source code for the Post component in React Developer Tools was different from the source code written in your post.jsx file. This is because React Developer Tools is pulling the code from the bundle.js file generated by webpack and not the original source code.

Luckily, there is a way we can debug React with the original source code using files known as sourcemaps. Put simply, a sourcemap is a file containing mappings from one or more source files (ex. post.jsx) to a generated/transpiled JavaScript (ex. bundle.js). By including a sourcemap, the browser is able to determine where the transpiled code came from and display the original source code in the debugger.

To start generating sourcemaps with Webpack, we just have to set devtool: "source-map" in our webpack.config.js file. For your config file you can add it right after the resolve item.

  // entry, output, module ...
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  devtool: "source-map"
};

Now run the build process again. You should now see the file bundle.js.map inside /insta485/static/js/. This is the sourcemap that contains the mappings betwen bundle.js and the source files.

$ pwd
/Users/awdeorio/src/eecs485/p3-insta485-clientside
$ npx webpack
...
$ tree insta485/static/js/
insta485/static/js/
├── bundle.js
└── bundle.js.map

Now run and navigate to http://localhost:8000/, where you should be able to see the source code inside the developer tools.

$ ./bin/insta485run
...

Congrats! Now you can debug using the same process but now with the original React source code. For a more in depth explanation of sourcemaps, feel free to read this informative article.

End-to-end testing

You should also read the end-to-end testing tutorial. The tools mentioned in this tutorial are great for detail-oriented debugging, but we rely on end-to-end testing in order to make sure that the end user experiences all of the correct behavior. Some people find it helpful to have Cypress constantly open and running tests, allowing you to use your browser’s dev tools during a test at different points in time. Another option is to use your browser’s dev tools normally while working on a feature, checking that your React components are transferring state in expected ways, and then run end-to-end tests after you’re finished with the feature. Just note that the React Developer Tools browser extension may be tricky to use with Cypress, so you may want to use that only in a normal browser window.

Acknowledgments

Original document written by Andrew DeOrio awdeorio@umich.edu.

This document is licensed under a Creative Commons Attribution-NonCommercial 4.0 License. You’re free to copy and share this document, but not to sell it. You may not share source code provided with this document.