React By Example: Part 4

John Tucker
Frontend Weekly
Published in
6 min readJun 4, 2017

Dissecting a React application.

This article is part of a series (starting with React By Example: Part 1) of articles that, through a number of progressively more complicated examples, explores the React JavaScript library. The examples are available as a GitHub repository.

In this article we will dissect the sample React application that is generated by Create React App (CRA).

GIT Configuration

The file README.md is markdown formatted documentation that provides the copy for the main page of a GIT repository.

The hidden file .gitignore is used by the GIT version control system; indicates which files to not track.

.gitignore

# See https://help.github.com/ignore-files/ for more about ignoring files.# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

Package Managment

The directory node_modules and two files package.json and yarn.lock are used with Node.js package management.

The hundreds of files in node_modules are all the Node.js packages that CRA, depends on; some get bundled into the final output (for example React) but most are used in the build process.

While yarn.lock is not intended to be human-readable, package.json is:

package.json

{
"name": "my-app",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "1.0.6"
},
"dependencies": {
"react": "^15.5.4",
"react-dom": "^15.5.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}

The devDependencies section defines the dependencies that are used in the build process while those in the dependencies get bundled into the final output.

note: The hundreds of packages in node_modules arise from the cascading tree of dependencies.

The scripts section define the commands, e.g., yarn start and yarn build, that one can use with this project. If you were wondering, react-scripts, is a script defined in the special folder node_modules/.bin

Public

The files in the public folder get copied (with content injected into them) to the output build folder.

favicon.ico is an optional icon used for the browser’s favorites / bookmarks / shortcuts features.

manifest.json, new to me, is an optional file used with Android devices; not going to discuss in this series.

index.html is the entry point to the application, i.e., the file that the browser first loads. During the build process, references to the bundled JavaScript and CSS files are injected.

public/index.html

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

Of particular importance is the <div id=”root”></div> line in index.html; React renders all the DOM inside this div; as we develop our React application, we never have to separately edit any HTML files. This leads us to one of the benefits of a React application over our reference application.

While historically considered a good thing, separation of concerns, having to maintain the HTML and JavaScript in separate files is a common source of problems. For example, in our reference application the strings counter and increment need to be the same in both files (a source of typos).

Build

The build folder, created after running yarn build, is the folder that is deployed to a server (to serve up the application); none of the files are intended to be human-readable.

The files asset-manifest.json and service-worker.js are used to optimize for offline behavior (nothing to do with React) and as such will not discuss them further.

The files favicon.ico and manifest.json were copied over from the public folder we discussed earlier.

The file index.html, was copied over from public, injected with references to the CSS and JavaScript file.

The files in static/css are the CSS file and its source map (used to make debugging easier).

Likewise the files in static/js are the JavaScript file and its source map.

Finally, the files in static/media are images, etc., that were imported into our application (and were too big to convert to data URLs).

Source (Introducing JSX)

The src folder is where we focus our attention on for the remainder of this series; it is where we store the source code that ultimately gets bundled into the deploy-able application in the build folder.

First we are going to ignore both src/registerServiceWorker.js (service workers) and src/App.test.js (testing) as neither are React specific (and entirely optional).

The index.css and App.css are simply CSS files that are imported into the application.

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Observations

  • Because we spent time in earlier articles on the build process, all of the import statements should be familiar.
  • While we will leave them in, we will ignore the registerServiceWorker lines; we could easily remove them without relevant impact.
  • As in our reference example, document.getElementById(‘root’) simply returns the DOM element with the id of root.
  • The <App /> entry is called JSX; it is simply an abbreviation of the actual JavaScript code: React.createElement(App, null, null)
  • By expanding the JSX, we can now understand why we needed to import both React and App.

The key functionality of the line starting with ReactDOM, is to create an instance of an App object (called a component) and take any rendered HTML it generates and insert it into the DOM object with id of root. This is much like what we did with innerHTML in our reference example.

src/App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;

Observations

  • Again, the import, export, and destructuring syntax should be familiar.
  • The class syntax is a JavaScript ES2015 feature; in this case we are creating a new class, App, that extends (the functionality) of a Component by providing a render method.
  • What looks like HTML is actually JSX shorthand, e.g., notice the use of className instead of class (a reserved word in JavaScript).
  • The difference (use of curly brackets) between {logo} and “logo” is that the former passes its contents as JavaScript (in this case the variable logo) and the other is simply passing the string ‘logo’.

equivalent portion of src/App.js

...
React.createElement(
'div',
{ className: 'App' },
React.createElement(
'div',
{ className: 'App-header' },
React.createElement(
'img',
{
src: logo,
className: 'App-logo',
alt: 'logo'
},
null
),
React.createElement(
'h2',
null,
'Welcome to React'
)
),
React.createElement(
'p',
{ className: 'App-intro' },
'To get started, edit ',
React.createElement(
'code',
null,
'src/App.js'
),
' and save to reload.'
)
)
...

If you have written vanillaJS (no libraries used) JavaScript, you would have been using a combination of the following DOM manipulation commands to accomplish the what the JSX does:

  • document.createElement: Function that creates a DOM element
  • setAttribute: Method of DOM element to set attribute
  • classList.add: Property of DOM element and its method to add a class.
  • appendChild: Method of DOM element to append a child.

Now that we appreciate what is under-the-hood of JSX we will use it without thinking about how it works.

The Next Part

In the next part, React by Example: Part 5, we will re-implement our counter application with React and introduce several new React concepts: state and event handling.

--

--

John Tucker
Frontend Weekly

Broad infrastructure, development, and soft-skill background