Debugging React Applications

The temperature in the Twin Cities of Minneapolis and St. Paul in the past couple days has dropped a few degrees. We just started the month of August which should be midsummer. My wife always says that around the birthday of one of our sons (which is around mid March) fall arrives. I do just do not want to believe that summer is almost over. To tell you the truth, COVID-19 has not helped and to top it off this year the Minnesota State Fair has been cancelled. The fair is what marks the end of summer around here.

I was expecting an email to get something outside work done, but it did not arrive. Hopefully I will be able to work on it this coming Friday. My wife wants to visit my son who lives in Wisconsin next weekend. We chat on-line with Jitsi pretty much every day, but nothing beats chatting in person. We both are very good at keeping social distancing practices. We do not have too many weekends left before school starts. That will be a game changer for everyone that has kids attending K-12 and / or college. We need to find a way to get our country and the world back on track.

In a previous post I mentioned that we live of a private road. The road was starting to show age signs. In addition, several neighbors were experiencing issues drainage issues when we received large amounts of rain due to summer storms. After a couple weeks of work, we have large underground drainage, replaced road curb, and a nice and smooth new road surface.

For the next couple times of garbage collection days, we have been asked to put leave our bins in the main road. The home owners association does not want heavy trucks on the recently resurfaced road.

Now to the main subject of this post which will be quite short.

As you know I have been taking an ACM on-line React course. The course is by O’Reilly. Chapter 6 which I finished last week; covers debugging React applications. In my humble opinion, if you are interested in this topic, I would suggest signing up for this (or any other comparable) course. I can only show the resulting state of the application files after inducing and then correcting a set of bugs.

I completed chapter six and then created a GitHub repository to hold the code for the project.

# **** open command prompt console on Windows 10 ****
Microsoft Windows [Version 10.0.18363.959]
(c) 2019 Microsoft Corporation. All rights reserved.

# **** ****
C:\Users\johnc>dir
07/16/2020  07:39 AM    <DIR>          .
07/16/2020  07:39 AM    <DIR>          ..
05/13/2020  03:07 PM                57 .angular-config.json
06/18/2020  04:50 PM    <DIR>          .atom
05/13/2020  03:03 PM    <DIR>          .config
09/22/2019  08:00 AM    <DIR>          .eclipse
03/15/2020  08:38 AM                59 .gitconfig
06/19/2020  08:40 AM               119 .node_repl_history
04/23/2020  11:11 AM    <DIR>          .p2
05/07/2020  08:11 AM         1,005,502 .pipwin
04/21/2020  08:07 AM    <DIR>          .pylint.d
09/22/2019  08:00 AM    <DIR>          .tooling
03/10/2020  03:53 PM    <DIR>          .vscode
07/15/2020  09:12 AM    <DIR>          3D Objects
07/15/2020  09:12 AM    <DIR>          Contacts
04/08/2020  07:59 AM    <DIR>          ContainsCloseNums
02/17/2020  03:52 PM    <DIR>          Documents
07/23/2020  10:04 AM    <DIR>          Downloads
09/22/2019  07:57 AM    <DIR>          eclipse
09/22/2019  07:59 AM    <DIR>          eclipse-workspace_0
07/15/2020  09:12 AM    <DIR>          Favorites
07/15/2020  09:12 AM    <DIR>          Links
07/15/2020  09:12 AM    <DIR>          Music
05/13/2020  03:49 PM    <DIR>          my-app
09/12/2019  04:36 PM    <DIR>          NCH Software Suite
07/16/2020  07:39 AM    <DIR>          node_modules
08/03/2020  07:27 AM    <DIR>          OneDrive
07/16/2020  07:39 AM             3,871 package-lock.json
05/04/2020  03:42 PM    <DIR>          pipwin
07/15/2020  09:12 AM    <DIR>          Saved Games
07/15/2020  09:12 AM    <DIR>          Searches
05/11/2020  03:04 PM    <DIR>          source
07/15/2020  09:12 AM    <DIR>          Videos
05/05/2020  01:30 PM    <DIR>          vimfiles
06/10/2020  10:50 AM    <DIR>          workspace0
07/28/2020  11:08 AM    <DIR>          workspace1
05/05/2020  01:51 PM             3,281 _viminfo

# **** desired directory ****
C:\Users\johnc>cd workspace1

# **** ****
C:\Users\johnc\workspace1>dir
07/28/2020  11:08 AM    <DIR>          .
07/28/2020  11:08 AM    <DIR>          ..
07/08/2020  07:44 AM    <DIR>          base-syntax
07/27/2020  08:50 AM    <DIR>          Combinations
07/01/2020  08:58 AM    <DIR>          HospitalsHillClimbing
07/23/2020  10:15 AM    <DIR>          KittysCalculations
06/22/2020  11:34 AM    <DIR>          learnangular5
07/09/2020  02:21 PM    <DIR>          lists-conditionals
07/28/2020  11:09 AM    <DIR>          LowestCommonAncestor
07/02/2020  08:48 AM    <DIR>          react-complete-guide
07/22/2020  08:03 AM    <DIR>          styling-components-elements
07/11/2020  10:18 AM    <DIR>          TheMasseuse
07/22/2020  04:36 PM    <DIR>          TreePreorderTraversal

# **** desired directory ****
C:\Users\johnc\workspace1>cd styling-components-elements

# **** ****
C:\Users\johnc\workspace1\styling-components-elements>git init
Reinitialized existing Git repository in C:/Users/johnc/workspace1/styling-components-elements/.git/

# **** check if we are in the proper remote repository (we are not) ****
C:\Users\johnc\workspace1\styling-components-elements>git remote -v
origin  https://github.com/JohnCanessa/styling-components-elements.git (fetch)
origin  https://github.com/JohnCanessa/styling-components-elements.git (push)

# **** change repository ****
C:\Users\johnc\workspace1\styling-components-elements>git remote set-url origin https://github.com/JohnCanessa/DebuggingReactApp.git

# **** check the name of the remote repository (looks good) ****
C:\Users\johnc\workspace1\styling-components-elements>git remote -v
origin  https://github.com/JohnCanessa/DebuggingReactApp.git (fetch)
origin  https://github.com/JohnCanessa/DebuggingReactApp.git (push)

# **** ****
C:\Users\johnc\workspace1\styling-components-elements>dir
07/22/2020  08:03 AM    <DIR>          .
07/22/2020  08:03 AM    <DIR>          ..
07/22/2020  07:59 AM                59 .gitignore
07/15/2020  08:10 AM    <DIR>          .vscode
07/22/2020  08:01 AM    <DIR>          config
10/19/2017  10:31 AM               374 how-to-use.txt
07/22/2020  08:01 AM    <DIR>          node_modules
07/22/2020  08:01 AM           364,821 package-lock.json
07/22/2020  08:01 AM             2,648 package.json
07/15/2020  08:08 AM    <DIR>          public
10/19/2017  10:29 AM           105,919 README.md
07/22/2020  08:01 AM    <DIR>          scripts
07/28/2020  08:54 AM    <DIR>          src

# **** check we are skipping pushing the /node_modules folder ****
C:\Users\johnc\workspace1\styling-components-elements>type .gitignore
# **** ignore the node_modules folder ****
/node_modules/*

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/App.js
        modified:   src/Person/Person.js

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        src/ErrorBoundary/

no changes added to commit (use "git add" and/or "git commit -a")

# **** add the source code files that had been modified and added ****
C:\Users\johnc\workspace1\styling-components-elements>git add .
warning: LF will be replaced by CRLF in src/App.js.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in src/Person/Person.js.
The file will have its original line endings in your working directory

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   src/App.js
        new file:   src/ErrorBoundary/ErrorBoundary.js
        modified:   src/Person/Person.js

# **** commit the code ****
C:\Users\johnc\workspace1\styling-components-elements>git commit -m "first commit"
[master 9907ed3] first commit
 3 files changed, 50 insertions(+), 15 deletions(-)
 create mode 100644 src/ErrorBoundary/ErrorBoundary.js

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
nothing to commit, working tree clean

# **** push the changes to GitHub ****
C:\Users\johnc\workspace1\styling-components-elements>git push origin master
Enumerating objects: 55, done.
Counting objects: 100% (55/55), done.
Delta compression using up to 12 threads
Compressing objects: 100% (52/52), done.
Writing objects: 100% (55/55), 138.96 KiB | 7.72 MiB/s, done.
Total 55 (delta 11), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (11/11), done.
To https://github.com/JohnCanessa/DebuggingReactApp.git
 * [new branch]      master -> master

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
nothing to commit, working tree clean

# **** check the log ****
C:\Users\johnc\workspace1\styling-components-elements>git log -v
commit 9907ed359aac8dd39455e3ce08822dea76edaf84 (HEAD -> master, origin/master)
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Mon Aug 3 08:48:57 2020 -0500

    first commit

commit e5b0925f02b8c44a04a37a6a8ccba36ec3297f81
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Mon Jul 27 11:22:19 2020 -0500

    done with this chapter

commit 7fbb5e168401968d9ed1849112589723124c4046
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Wed Jul 22 08:04:41 2020 -0500

    removed styled components from App.js

GitHub runs a bot named Dependabot which may or may not generate warnings at several levels. I went after the first critical alert.

{
"name": "react-complete-guide",
"version": "0.1.0",
"private": true,
"dependencies": {

"autoprefixer": "7.1.2", <=== added

"babel-core": "6.25.0",
"babel-eslint": "7.2.3",
:::: :::: ::::

Edited the package.json file and added a line as suggested:

# **** after modifying ****
C:\Users\johnc\workspace1\styling-components-elements>npm install
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.2 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

added 2 packages from 1 contributor, updated 2 packages and audited 1288 packages in 9.995s

1 package is looking for funding
  run `npm fund` for details

found 1549 vulnerabilities (793 low, 41 moderate, 713 high, 2 critical)
  run `npm audit fix` to fix them, or `npm audit` for details

# **** ****
C:\Users\johnc\workspace1\styling-components-elements>npm audit fix
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN notsup Unsupported engine for watchpack-chokidar2@2.0.0: wanted: {"node":"<8.10.0"} (current: {"node":"12.18.1","npm":"6.14.5"})
npm WARN notsup Not compatible with your version of node/npm: watchpack-chokidar2@2.0.0
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules\watchpack\node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\watchpack-chokidar2\node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.1.2 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ react-dev-utils@4.2.3
added 204 packages from 104 contributors, removed 60 packages, updated 38 packages and moved 3 packages in 52.072s

3 packages are looking for funding
  run `npm fund` for details

fixed 1457 of 1549 vulnerabilities in 1288 scanned packages
  51 vulnerabilities required manual review and could not be updated
  6 package updates for 41 vulnerabilities involved breaking changes
  (use `npm audit fix --force` to install breaking changes; or refer to `npm audit` for steps to fix these manually)

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   package-lock.json
        modified:   package.json
        modified:   src/Person/Person.js

no changes added to commit (use "git add" and/or "git commit -a")

C:\Users\johnc\workspace1\styling-components-elements>git add
Nothing specified, nothing added.
hint: Maybe you wanted to say 'git add .'?
hint: Turn this message off by running
hint: "git config advice.addEmptyPathspec false"

C:\Users\johnc\workspace1\styling-components-elements>git add .
warning: LF will be replaced by CRLF in package-lock.json.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in package.json.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in src/Person/Person.js.
The file will have its original line endings in your working directory

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   package-lock.json
        modified:   package.json
        modified:   src/Person/Person.js

# **** commit changes ****
C:\Users\johnc\workspace1\styling-components-elements>git commit -m "added dependency to address some dependabot messages"
[master bf58913] added dependency to address some dependabot messages
 3 files changed, 2021 insertions(+), 742 deletions(-)

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
nothing to commit, working tree clean

C:\Users\johnc\workspace1\styling-components-elements>git push origin master
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 12 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 19.13 KiB | 3.83 MiB/s, done.
Total 7 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), completed with 5 local objects.
remote:
remote: GitHub found 36 vulnerabilities on JohnCanessa/DebuggingReactApp's default branch (3 critical, 14 high, 14 moderate, 5 low). To find out more, visit:
remote:      https://github.com/JohnCanessa/DebuggingReactApp/network/alerts
remote:
To https://github.com/JohnCanessa/DebuggingReactApp.git
   9907ed3..bf58913  master -> master

# **** check git status ****
C:\Users\johnc\workspace1\styling-components-elements>git status
On branch master
nothing to commit, working tree clean

# **** check the log ****
C:\Users\johnc\workspace1\styling-components-elements>git log
commit bf58913bd31ce1be25ad57297a7307fcfd477d80 (HEAD -> master, origin/master)
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Mon Aug 3 09:12:36 2020 -0500

    added dependency to address some dependabot messages

commit 9907ed359aac8dd39455e3ce08822dea76edaf84
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Mon Aug 3 08:48:57 2020 -0500

    first commit

commit e5b0925f02b8c44a04a37a6a8ccba36ec3297f81
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Mon Jul 27 11:22:19 2020 -0500

    done with this chapter

commit 7fbb5e168401968d9ed1849112589723124c4046
Author: JohnCanessa <john.canessa@gmail.com>
Date:   Wed Jul 22 08:04:41 2020 -0500

    removed styled components from App.js

I guess I need to repeat the process a few time for the remaining critical conditions outlined by Dependabot. I will get it done in the near future.

Error Boundaries are used to avoid an application to crash. To me it is like the typically used try-catch construct found in many programming languages.

In the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to emit cryptic errors on next renders. These errors were always caused by an earlier error in the application code, but React did not provide a way to handle them gracefully in components, and could not recover from them.

Introducing Error Boundaries – A JavaScript error in a part of the UI shouldn’t break the whole app. To solve this problem for React users, React 16 introduces a new concept of an “error boundary”.

Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in life cycle methods, and in constructors of the whole tree below them.

import React from 'react';

import classes from './Person.css';

// **** ****
const person = ( props ) => {

    // ???? generate an error ????
    const rnd = Math.random();

    if (rnd > 0.9) {
        throw new Error('Something went wrong');
    }

    return (
        <div className={classes.Person}>
            <p onClick={props.click}>I'm {props.name} and I am {props.age} years old!</p>
            <p>{props.children}</p>
            <input type="text" onChange={props.changed} value={props.name} />
        </div>
    )
};

// **** ****
export default person;

This last listing shows the final state of the Persons.js file.

import React, { Component } from 'react';

// **** this is a higher order component ****
class ErrorBoundary extends Component {
    state = {
        hasError: false,
        errorMessage: ''
    }

    componentDidCatch = (error, info) => {
        this.setState({hasError: true, errorMessage: error});
    }

    render() {
        if (this.state.hasError) {
            return <h1>{this.state.errorMessage}</h1>;
        } else {
            return this.props.children;
        }
    }
}

// **** ****
export default ErrorBoundary;

This last listing shows the final state of the ErrorBoundary.js file.

import React, { Component } from 'react';
import classes from './App.css';
import Person from './Person/Person';

import ErrorBoundary from './ErrorBoundary/ErrorBoundary';

// **** ****
class App extends Component {
  state = {
    persons: [
      { id: 'asfa1', name: 'Max', age: 28 },
      { id: 'vasdf1', name: 'Manu', age: 29 },
      { id: 'asdf11', name: 'Stephanie', age: 26 }
    ],
    otherState: 'some other value',
    showPersons: false
  }


  nameChangedHandler = ( event, id ) => {
    const personIndex = this.state.persons.findIndex(p => {

      return p.id === id;           // correct
      // return p.userID === id;    // incorrect

    });

    const person = {
      ...this.state.persons[personIndex]
    };

    // const person = Object.assign({}, this.state.persons[personIndex]);

    // **** ****
    person.name = event.target.value;       // correct
    // person.name = event.input.value;     // incorrect (look at documentation for event)

    const persons = [...this.state.persons];
    persons[personIndex] = person;

    this.setState( {persons: persons} );
  }


  deletePersonHandler = (personIndex) => {
    // const persons = this.state.persons.slice();
    const persons = [...this.state.persons];
    persons.splice(personIndex, 1);
    this.setState({persons: persons});
  }

  togglePersonsHandler = () => {
    const doesShow = this.state.showPersons;
    this.setState( { showPersons: !doesShow } );
  }

  // **** ****
  render () {
    let persons = null;
    let btnClass = '';

    if ( this.state.showPersons ) {
      persons = (
        <div>
          {this.state.persons.map( (person, index) => {
            return <ErrorBoundary key={person.id}>
              <Person
                click={() => this.deletePersonHandler( index )}
                name={person.name} 
                age={person.age}
                changed={( event ) => this.nameChangedHandler(event, person.id)} />
            </ ErrorBoundary>
          })}
        </div>
      );

      btnClass = classes.Red;
    }

    // **** must define classes in App.css ****
    const assignedClasses = [];
    if (this.state.persons.length <= 2) {
      assignedClasses.push(classes.red);        // classes = ['red']
    }
    if (this.state.persons.length <= 1) {
      assignedClasses.push(classes.bold);       // classes = ['red', 'bold']
    }
    if (this.state.persons.length <= 0) {
      assignedClasses.push(classes.underline);  // classes =  ['red', 'bold', 'underline']
    }

    // ???? ????
    console.log("persons: " + persons);

    // **** ****
    return (
      <div className={classes.App}>
        <h1>Hi, I'm a React App</h1> 
        <p className={assignedClasses.join(' ')}>This is really working!</p>

        <button className={btnClass} onClick={this.togglePersonsHandler}>
          Toggle Persons
        </button>

        {persons}
      </div>
    );
    // return React.createElement('div', {className: 'App'}, React.createElement('h1', null, 'Does this work now?'));
  }
}

// **** ****
export default App;

This last listing shows the final state of the App.js file.

The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to serve of assistance with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a private message using the following address:  john.canessa@gmail.com. I will reply as soon as possible.

Keep on reading and experimenting. It is the best way to learn, become proficient, refresh your knowledge and enhance your developer toolset!

One last thing, many thanks to all 1,520 subscribers to my blog!!!

Keep safe during the COVID-19 pandemic and help restart the world economy.

John

Twitter:  @john_canessa

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.