Getting Started with React

This article gives a hands-on tutorial on setting up a React application.

What is React?

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It allows building a complex application from ground up by isolated pieces of code, usually called components. The idea of React is not new but within just a few years, it has achieved great adoptions among many companies and organizations. The stable and friendly APIs make React the first choice for building a Cloud Native Application.

Play Around With React

Create a New App

create-react-app is the simplest way to setup the boilerplate template code for a new React application.

Let's create a new project with the name of frontend.

$ yarn create react-app frontend
$ cd frontend
$ yarn start

Once finished, you should now see the directory as below.

frontend
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    └── serviceWorker.js
  • README.md holds the description of the project.
  • node_modules holds all of the dependencies of the React application.
  • package.json includes the metadata of the project. The dependencies described in package.json can be installed by yarn install.
  • .gitignore claims those should not be included into version control, such as node_modules. The reason we don't check in some files are usually that they can be generated by other commands.
  • Files in directory public are those going to be distributed to user browsers.
  • Files in directory src are React components, which will be built into dist directory.

Start React App

Runs the app in development mode.

$ yarn start

Open http://localhost:3000 to view it in the browser.

Test React App

Run below command in another terminal session.

$ yarn test

You should see all test passed.

Make the First Change

Leave the yarn start process running and let's modify the file src/App.js in your favorite editor.







 







import React, { Component } from 'react';

class App extends Component {
  render() {
    return (
      <div className="App">
        <p>Hello World</p>
      </div>
    );
  }
}

export default App;

You should see the page automatically reloaded in your browser with only text "Hello World".

hello world

Handle Routes

Install react-router-dom.

$ yarn add react-router-dom

Import the router.


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 



import React from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";

const Home = () => (
  <div className="App">
    <p>Hello World</p>
  </div>
);

const App = () => (
  <Router>
    <div>
      <Route path="/" exact component={Home} />
    </div>
  </Router>
);

export default App;

Setup 404 Page

Create a NotFound component.


 







 
 
 
 
 



 

 
 





import React  from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

const Index = () => (
  <div className="App">
    <p>Hello World</p>
  </div>
);

const NotFound = () => (
  <div className="App">
    <p>Not Found</p>
  </div>
)

const App = () => (
  <Router>
    <Switch>
      <Route path="/" exact component={Index} />
      <Route component={NotFound} />
    </Switch>
  </Router>
);

export default App;

By browsing to the page http://127.0.0.1:3000/404, or replacing 404 to any path, you should see "Not Found" on the page. By browsing to the page http://127.0.0.1:3000, you should see "Hello World" on the page!

404

Setup App Page

So far, we have two pages. Let's move them into a sub-directory to organize code better. Create directory src/pages before saving below two files src/pages/not-found.js and src/pages/home.js.

// src/pages/not-found.js
import React from 'react';

export default () => (
  <div className="App">
    <p>Not Found</p>
  </div>
)
// src/pages/home.js
import React from 'react';

export default () => (
  <div className="App">
    <p>Hello World</p>
  </div>
);

Finally, let's import the two components into src/App.js.




 
 












import React from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

import Home from './pages/home';
import NotFound from './pages/not-found';

const App = () => (
  <Router>
    <Switch>
      <Route path="/" exact component={Home} />
      <Route component={NotFound} />
    </Switch>
  </Router>
);

export default App;

Why use React?

Declarative

Writing interactive UIs is harder than many people thought, which involves a lot of internal states and transitions. Have you ever considered implementing a loading spinner? When should the component show the spinner? How fast should the spinner spin? What if the spinner load forever? When is the exit point of loading? Should it apply with a blurring background? These hidden states make code complex if using inappropriate programming paradigm. Imperative code is suitable for implementing algorithms, but never for managing a large amount of internal states. To address it, we need declarative style code.

For example, below JavaScript function Timer has an internal state seconds. The component returns a DOM with ever changing seconds, though the caller of the function Timer need not to know the existence of seconds. When setInterval triggers a value changing in the next moment, React will efficiently update and render it to the browser DOM.

function Timer() {
  const { seconds, setSeconds } = useState(0);
  setInterval(() => setSeconds(seconds + 1), 1000);
  return <div>Seconds: {seconds}</div>;
}

We just used 3 lines of code implementing below things:

  • State declaration,
  • State changing,
  • State rendering.

It's super powerful when the component has more internal states. The declarative style makes the code predicable and easier to debug.

Virtual DOM is Fast

DOM manipulations can be slow if implemented inappropriately. For example, you have a list containing hundreds of items. Rebuilding the entire list to the DOM could be very inefficient. To address this problem, we can build the DOM for those changed items only. Virtual DOM is such a technique for this kind of problem.

In short, React updates DOM in below steps:

  • Your React code updates virtual DOM.
  • React compares the virtual DOM to previous version and figure out what actual DOM need to be changed.
  • React patches these changes to the page.
  • Changes are reflected to the browser screen.

In React, every DOM on the page has a corresponding virtual DOM object. The idea is, manipulating DOM is slow but manipulating virtual DOM in memory is fast. By comparing the virtual DOM with previous version, we can quickly spot a minimal set of changes and apply them to the page. Applying a minimal set of changes is way faster than building the entire list rendering.

One-way Data Binding

Essential Knowledge

JSX

You might have noticed the funny XML-like syntax in previous example, <div>Seconds: {seconds}</div>. It's neither string nor XML, but just a syntax extension to JavaScript. You can put any valid JavaScript expressions within {braces} inside the component. Most React developers are keen to use JSX syntax to make the React Element easier to write.

Under the hood, the <div></div> is translated to React.createElement('div'). Just as its name, JSX is actually creating React "elements". To give you a glance of the nesting elements, the code <div><span>hello</span></div> is equivalent to:

React.createElement('div',
  React.createElement('span',
    'hello'
  )
)

You can certainly use plain React.createElement to write code. But since JSX provides the syntax sugar making your life easier, why bother not using it? The JSX also indicates a design pattern, separate concerns. Unlike separating logics into templates, styles, models, and so on, each component is a standalone unit that contains all of the given pieces. Some might argue it's uncomfortable to fit all them in, but it has turned out a successful programming paradigm with so many open-sourced, high quality React-based components.

Virtual DOM

DOM stands for Document Object Model and is an abstraction of a structured text. HTML code is the structured tree object and Elements of corresponding HTML code become nodes in the DOM. To sum up, DOM is an in-memory representation of HTML code.

Nowadays, there are usually hundreds of thousands of DOM in a single page, not to mention that each one could attach events, styles, etc. A typical jQuery-like framework would handle the issue by finding nodes by selectors first, and then update if needed.

<div id="message">Hello World</div>
<script>
$("#message").html("Hands-On Cloud Native Application").
</script>

However, the finding operations on a page including a large number of DOM nodes are slow. Besides, managing these tangled manipulation code could be a mess.

Virtual DOM became one of the most popular solutions. To be fair, React did not invent it but integrated it into its core. The Virtual DOM is an abstraction of the HTML DOM. So, considering HTML DOM being an abstraction of HTML code, why bother applying two layers of abstractions to get changes to the page? The short answer is abstractions bring more values, and these values help us overcome performance issue and reduce management cost.

Actual DOM

You might be curious what is the entry point of the virtual DOM becoming actual DOM. The answer is ReactDom.render() function. There is usually only one DOM node on the page that is acting root DOM node.

<div id="root"></div>

ReactDOM.render() function renders a React element to the root node.

ReactDOM.render(
  <div id="message">Hands-On Cloud Native Application</div>,
  document.getElementById('root')
);

It might seem similar to above jQuery example, but they have a big difference. The ReactDOM.render() only gets called once. Once you create an element, React will take over the rest and apply any virtual DOM changes to the DOM.

Components

React components are independent, isolated, and reusable pieces of React code. They're building blocks of the entire React application. Think of it as the functions to JavaScript. It looks just as a normal JavaScript function, passing in props argument and sending out a React element.

function HandsOn(props) {
  return <div id="message">Hands-On {props.name}</div>
}

Except the function components, you can also choose to write it in a form as a class. They are the same thing in different style.

class HandsOn extends React.Component {
  render() {
    return <div id="message">Hands-On {props.name}</div>
  }
}

Using a component is by composing it to another component til the ReactDOM.render(). For example,

ReactDOM.render(
  <div id="app">
    <HandsOn name="Cloud Native Application" />
  </div>,
  document.getElementById('root')
);

Two trivial things to remember are the naming convention and the immutable props. First, The name of component should always start with a capital letter. Otherwise, React will consider it as a normal HTML tag and won't generate the expanded virtual DOM. Second, you shouldn't change the value in props as all React components must act like pure functions.

States

Since you can't change props, now you might want to know what if something need to be changed? The answer is state. States are mutable variables within the scopes of components. The way to consider props and states can be like using a fan; you set a fan at level 1/2/3 and the level is one of the props; the fan starts spinning and the spinning rate is one of the states.

Since React 16.8, you can now use Hooks, which we'll explain later, to consume states. Before using a state, you need to declare the state by useState:

function Timer() {
  const { seconds, setSeconds } = useState(0);
  setInterval(() => setSeconds(seconds + 1), 1000);
  return <div>Seconds: {seconds}</div>;
}

The useState(0) declares a state variable with initial value 0. You cannot consume the state variable outside the scope of Timer component. Each state should be declared once with useState(). It returns a pair of values, the current value and the function to update this value.

You can write an equivalent code in a traditional ES6 class style, though it's more verbose.

class Timer extends React.Component {
  constructor(props){
    super(props);
    this.state = { seconds: 0 };
  }

  componentDidMount() {
    setInterval(() => this.setState({ seconds: this.state.seconds+1 }), 1000);
  }

  render() {
    return <div>Seconds: {this.state.seconds}</div>
  }
}

Events

Events are objects representing what happen on the DOM elements. React handle events is very similar to how browser handle DOM events. Below example shows how to handle a click event.

function Counter() {
  const { count, setCount } = useState(0);
  return <div onClick={() => setCount(count+1)}>{count}</div>;
}

You might noticed it's using onClick instead onclick as specified in W3C events https://www.w3.org/TR/DOM-Level-3-Events/. And yes, React events are named using camelCase. Also, you pass a function as the parameter for the event hook.

Hooks

Hook is a way to define React component without writing verbose class code. Since conceptually a React component is just a pure function, it makes sense to define React component in declarative way and in function-style. In short, hooks are just plain JavaScript functions that let you "hook into" React state and life-cycle by a set of APIs.

You have seen the state hook, useState, which is for declaring a state variable. There are some other hooks, such as effect hook. Effect hooks are for performing side-effecting operations. Since these operations cannot be re-done during the next time React render the element, the effect hooks runs a one-off "job" and re-render the element when the job is finished. For example,

function Counter() {
  const { count, setCount } = useState(0);
  useEffect(() => {
    console.log(count);
  });
  return <div onClick={() => setCount(count+1)}>{count}</div>;
}

Some caveats of writing hooks are:

  • Don't place hooks in loops, conditions, or nested functions. It's just making the application too slow.

Functional Programming

Summary

References

facebook/create-react-app, github.com, https://github.com/facebook/create-react-app

React (JavaScript Library), en.wikipedia.org, https://en.wikipedia.org/wiki/React_(JavaScript_library)

Pomodoro Technique, en.wikipedia.org, https://en.wikipedia.org/wiki/Pomodoro_Technique

React: The Virtual DOM, https://www.codecademy.com/articles/react-virtual-dom

The difference between Virtual DOM and DOM, https://reactkungfu.com/2015/10/the-difference-between-virtual-dom-and-dom/