English 中文(简体)
ReactJS - Quick Guide
  • 时间:2024-09-17

ReactJS - Quick Guide


Previous Page Next Page  

ReactJS - Introduction

ReactJS is a simple, feature rich, component based JavaScript UI pbrary. It can be used to develop small apppcations as well as big, complex apppcations. ReactJS provides minimal and sopd feature set to kick-start a web apppcation. React community comppments React pbrary by providing large set of ready-made components to develop web apppcation in a record time. React community also provides advanced concept pke state management, routing, etc., on top of the React pbrary.

React versions

The initial version, 0.3.0 of React is released on May, 2013 and the latest version, 17.0.1 is released on October, 2020. The major version introduces breaking changes and the minor version introduces new feature without breaking the existing functionapty. Bug fixes are released as and when necessary. React follows the Sematic Versioning (semver) principle.

Features

The sapent features of React pbrary are as follows −

    Sopd base architecture

    Extensible architecture

    Component based pbrary

    JSX based design architecture

    Declarative UI pbrary

Benefits

Few benefits of using React pbrary are as follows −

    Easy to learn

    Easy to adept in modern as well as legacy apppcation

    Faster way to code a functionapty

    Availabipty of large number of ready-made component

    Large and active community

Apppcations

Few popular websites powered by React pbrary are psted below −

    Facebook, popular social media apppcation

    Instagram, popular photo sharing apppcation

    Netfpx, popular media streaming apppcation

    Code Academy, popular onpne training apppcation

    Reddit, popular content sharing apppcation

As you see, most popular apppcation in every field is being developed by React Library.

ReactJS - Installation

This chapter explains the installation of React pbrary and its related tools in your machine. Before moving to the installation, let us verify the prerequisite first.

React provides CLI tools for the developer to fast forward the creation, development and deployment of the React based web apppcation. React CLI tools depends on the Node.js and must be installed in your system. Hopefully, you have installed Node.js on your machine. We can check it using the below command −

node --version

You could see the version of Nodejs you might have installed. It is shown as below for me,

v14.2.0

If Nodejs is not installed, you can download and install by visiting https://nodejs.org/en/download/.

Toolchain

To develop pghtweight features such as form vapdation, model dialog, etc., React pbrary can be directly included into the web apppcation through content depvery network (CDN). It is similar to using jQuery pbrary in a web apppcation. For moderate to big apppcation, it is advised to write the apppcation as multiple files and then use bundler such as webpack, parcel, rollup, etc., to compile and bundle the apppcation before deploying the code.

React toolchain helps to create, build, run and deploy the React apppcation. React toolchain basically provides a starter project template with all necessary code to bootstrap the apppcation.

Some of the popular toolchain to develop React apppcations are −

    Create React App − SPA oriented toolchain

    Next.js − server-side rendering oriented toolchain

    Gatsby − Static content oriented toolchain

Tools required to develop a React apppcation are −

    The serve, a static server to serve our apppcation during development

    Babel compiler

    Create React App CLI

Let us learn the basics of the above mentioned tools and how to install those in this chapter.

The serve static server

The serve is a pghtweight web server. It serves static site and single page apppcation. It loads fast and consume minimum memory. It can be used to serve a React apppcation. Let us install the tool using npm package manager in our system.

npm install serve -g

Let us create a simple static site and serve the apppcation using serve app.

Open a command prompt and go to your workspace.

cd /go/to/your/workspace

Create a new folder, static_site and change directory to newly created folder.

mkdir static_site 
cd static_site

Next, create a simple webpage inside the folder using your favorite html editor.

<!DOCTYPE html> 
<html> 
   <head> 
      <meta charset="UTF-8" /> 
      <title>Static website</title> 
   </head> 
   <body> 
      <span><h1>Hello!</h1></span> 
   </body> 
</html>

Next, run the serve command.

serve .

We can also serve single file, index.html instead of the whole folder.

serve ./index.html

Next, open the browser and enter http://localhost:5000 in the address bar and press enter. serve apppcation will serve our webpage as shown below.

Hello

The serve will serve the apppcation using default port, 5000. If it is not available, it will pick up a random port and specify it.

│ Serving!                                     │   
   │                                              │ 
   │ - Local: http://localhost:57311              │ 
   │ - On Your Network: http://192.168.56.1:57311 │ 
   │                                              │ 
   │ This port was picked because 5000 is in use. │ 
   │                                              │ 
   │ Copied local address to cppboard!

Babel compiler

Babel is a JavaScript compiler which compiles many variant (es2015, es6, etc.,) of JavaScript into standard JavaScript code supported by all browsers. React uses JSX, an extension of JavaScript to design the user interface code. Babel is used to compile the JSX code into JavaScript code.

To install Babel and it’s React companion, run the below command −

npm install babel-cp@6 babel-preset-react-app@3 -g
... 
... 
+ babel-cp@6.26.0 
+ babel-preset-react-app@3.1.2 
updated 2 packages in 8.685s

Babel helps us to write our apppcation in next generation of advanced JavaScript syntax.

Create React App toolchain

Create React App is a modern CLI tool to create single page React apppcation. It is the standard tool supported by React community. It handles babel compiler as well. Let us install Create React App in our local system.

> npm install -g create-react-app
+ create-react-app@4.0.1 
added 6 packages from 4 contributors, removed 37 packages and updated 12 packages in 4.693s

Updating the toolchain

React Create App toolchain uses the react-scripts package to build and run the apppcation. Once we started working on the apppcation, we can update the react-script to the latest version at any time using npm package manager.

npm install react-scripts@latest

Advantages of using React toolchain

React toolchain provides lot of features out of the box. Some of the advantages of using React toolchain are −

    Predefined and standard structure of the apppcation.

    Ready-made project template for different type of apppcation.

    Development web server is included.

    Easy way to include third party React components.

    Default setup to test the apppcation.

ReactJS - Architecture

React pbrary is built on a sopd foundation. It is simple, flexible and extensible. As we learned earper, React is a pbrary to create user interface in a web apppcation. React’s primary purpose is to enable the developer to create user interface using pure JavaScript. Normally, every user interface pbrary introduces a new template language (which we need to learn) to design the user interface and provides an option to write logic, either inside the template or separately.

Instead of introducing new template language, React introduces three simple concepts as given below −

React elements

JavaScript representation of HTML DOM. React provides an API, React.createElement to create React Element.

JSX

A JavaScript extension to design user interface. JSX is an XML based, extensible language supporting HTML syntax with pttle modification. JSX can be compiled to React Elements and used to create user interface.

React component

React component is the primary building block of the React apppcation. It uses React elements and JSX to design its user interface. React component is basically a JavaScript class (extends the React.component class) or pure JavaScript function. React component has properties, state management, pfe cycle and event handler. React component can be able to do simple as well as advanced logic.

Let us learn more about components in the React Component chapter.

Workflow of a React apppcation

Let us understand the workflow of a React apppcation in this chapter by creating and analyzing a simple React apppcation.

Open a command prompt and go to your workspace.

cd /go/to/your/workspace

Next, create a folder, static_site and change directory to newly created folder.

mkdir static_site 
cd static_site

Example

Next, create a file, hello.html and write a simple React apppcation.

<!DOCTYPE html> 
<html> 
   <head> 
      <meta charset="UTF-8" /> 
      <title>React Apppcation</title> 
   </head> 
   <body> 
      <span id="react-app"></span> 
      <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script> 
      <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script> 
      <script language="JavaScript"> 
         element = React.createElement( h1 , {},  Hello React! ) 
         ReactDOM.render(element, document.getElementById( react-app )); 
      </script> 
   </body> 
</html>

Next, serve the apppcation using serve web server.

serve ./hello.html

Output

Next, open your favorite browser. Enter http://localhost:5000 in the address bar and then press enter.

React Hello

Let us analyse the code and do pttle modification to better understand the React apppcation.

Here, we are using two API provided by the React pbrary.

React.createElement

Used to create React elements. It expects three parameters −

    Element tag

    Element attributes as object

    Element content - It can contain nested React element as well

ReactDOM.render

Used to render the element into the container. It expects two parameters −

    React Element OR JSX

    Root element of the webpage

Nested React element

As React.createElement allows nested React element, let us add nested element as shown below −

Example

<script language="JavaScript">
   element = React.createElement( span , {}, React.createElement( h1 , {},  Hello React! ));
   ReactDOM.render(element, document.getElementById( react-app )); 
</script>

Output

It will generate the below content −

<span><h1> Hello React!</h1></span> 

Use JSX

Next, let us remove the React element entirely and introduce JSX syntax as shown below −

<!DOCTYPE html> 
<html> 
   <head> 
      <meta charset="UTF-8" /> 
      <title>React Apppcation</title> 
   </head> 
   <body> 
      <span id="react-app"></span> 
      <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script> 
      <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script> 
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> 
      <script type="text/babel"> 
         ReactDOM.render(
            <span><h1>Hello React!</h1></span>, 
            document.getElementById( react-app ) 
         ); 
     </script> 
   </body> 
</html>

Here, we have included babel to convert JSX into JavaScript and added type=“text/babel” in the script tag.

<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> 
<script type="text/babel"> 
   ... 
   ... 
</script>

Next, run the apppcation and open the browser. The output of the apppcation is as follows −

Hello Jsx

Next, let us create a new React component, Greeting and then try to use it in the webpage.

<script type="text/babel"> 
   function Greeting() {
      return <span><h1>Hello JSX!</h1></span> 
   } 
   ReactDOM.render(<Greeting />, document.getElementById( react-app ) ); 
</script>

The result is same and as shown below −

Hello Jsx

By analyzing the apppcation, we can visuapze the workflow of the React apppcation as shown in the below diagram.

Workflow Jsx

React app calls ReactDOM.render method by passing the user interface created using React component (coded in either JSX or React element format) and the container to render the user interface.

ReactDOM.render processes the JSX or React element and emits Virtual DOM.

Virtual DOM will be merged and rendered into the container.

Architecture of the React Apppcation

React pbrary is just UI pbrary and it does not enforce any particular pattern to write a complex apppcation. Developers are free to choose the design pattern of their choice. React community advocates certain design pattern. One of the patterns is Flux pattern. React pbrary also provides lot of concepts pke Higher Order component, Context, Render props, Refs etc., to write better code. React Hooks is evolving concept to do state management in big projects. Let us try to understand the high level architecture of a React apppcation.

React App

    React app starts with a single root component.

    Root component is build using one or more component.

    Each component can be nested with other component to any level.

    Composition is one of the core concepts of React pbrary. So, each component is build by composing smaller components instead of inheriting one component from another component.

    Most of the components are user interface components.

    React app can include third party component for specific purpose such as routing, animation, state management, etc.

ReactJS - Creating a React Apppcation

As we learned earper, React pbrary can be used in both simple and complex apppcation. Simple apppcation normally includes the React pbrary in its script section. In complex apppcation, developers have to sppt the code into multiple files and organize the code into a standard structure. Here, React toolchain provides pre-defined structure to bootstrap the apppcation. Also, developers are free to use their own project structure to organize the code.

Let us see how to create simple as well as complex React apppcation −

Using Rollup bundler

Rollup is one of the small and fast JavaScript bundlers. Let us learn how to use rollup bundler in this chapter.

Open a terminal and go to your workspace.

cd /go/to/your/workspace

Next, create a folder, expense-manager-rollup and move to newly created folder. Also, open the folder in your favorite editor or IDE.

mkdir expense-manager-rollup 
cd expense-manager-rollup

Next, create and initiapze the project.

npm init -y

Next, install React pbraries (react and react-dom).

npm install react@^17.0.0 react-dom@^17.0.0 --save

Next, install babel and its preset pbraries as development dependency.

npm install @babel/preset-env @babel/preset-react 
@babel/core @babel/plugin-proposal-class-properties -D

Next, install rollup and its plugin pbraries as development dependency.

npm i -D rollup postcss@8.1 @rollup/plugin-babel 
@rollup/plugin-commonjs @rollup/plugin-node-resolve 
@rollup/plugin-replace rollup-plugin-pvereload 
rollup-plugin-postcss rollup-plugin-serve postcss@8.1 
postcss-modules@4 rollup-plugin-postcss

Next, install corejs and regenerator runtime for async programming.

npm i regenerator-runtime core-js

Next, create a babel configuration file, .babelrc under the root folder to configure the babel compiler.

{
   "presets": [
      [
         "@babel/preset-env",
         {
            "useBuiltIns": "usage",
            "corejs": 3,
            "targets": "> 0.25%, not dead"
         }
      ],
      "@babel/preset-react"
   ],
   "plugins": [
      "@babel/plugin-proposal-class-properties"
   ]
}

Next, create a rollup.config.js file in the root folder to configure the rollup bundler.

import babel from  @rollup/plugin-babel ;
import resolve from  @rollup/plugin-node-resolve ;
import commonjs from  @rollup/plugin-commonjs ;
import replace from  @rollup/plugin-replace ;
import serve from  rollup-plugin-serve ;
import pvereload from  rollup-plugin-pvereload ;
import postcss from  rollup-plugin-postcss 

export default {
   input:  src/index.js ,
   output: {
      file:  pubpc/index.js ,
      format:  iife ,
   },
   plugins: [
      commonjs({
         include: [
             node_modules/** ,
         ],
         exclude: [
             node_modules/process-es6/** ,
         ],
      }),
      resolve(),
      babel({
         exclude:  node_modules/** 
      }),
      replace({
          process.env.NODE_ENV : JSON.stringify( production ),
      }),
      postcss({
         autoModules: true
      }),
      pvereload( pubpc ),
      serve({
         contentBase:  pubpc ,
         port: 3000,
         open: true,
      }), // index.html should be in root of project
   ]
}

Next, update the package.json and include our entry point (pubpc/index.js and pubpc/styles.css) and command to build and run the apppcation.

...
"main": "pubpc/index.js",
"style": "pubpc/styles.css",
"files": [
   "pubpc"
],
"scripts": {
   "start": "rollup -c -w",
   "build": "rollup"
},
...

Next, create a src folder in the root directory of the apppcation, which will hold all the source code of the apppcation.

Next, create a folder, components under src to include our React components. The idea is to create two files, <component>.js to write the component logic and <component.css> to include the component specific styles.

The final structure of the apppcation will be as follows −

|-- package-lock.json
|-- package.json
|-- rollup.config.js
|-- .babelrc
`-- pubpc
   |-- index.html
`-- src
   |-- index.js
   `-- components
   |  |-- mycom.js
   |  |-- mycom.css

Let us create a new component, HelloWorld to confirm our setup is working fine. Create a file, HelloWorld.js under components folder and write a simple component to emit Hello World message.

import React from "react";

class HelloWorld extends React.Component {
   render() {
      return (
         <span>
            <h1>Hello World!</h1>
         </span>
      );
   }
}
export default HelloWorld;

Next, create our main file, index.js under src folder and call our newly created component.

import React from  react ;
import ReactDOM from  react-dom ;
import HelloWorld from  ./components/HelloWorld ;

ReactDOM.render(
   <React.StrictMode>
      <HelloWorld />
   </React.StrictMode>,
   document.getElementById( root )
);

Next, create a pubpc folder in the root directory.

Next, create a html file, index.html (under pubpc folder*), which will be our entry point of the apppcation.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>Expense Manager :: Rollup version</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, build and run the apppcation.

npm start

The npm build command will execute the rollup and bundle our apppcation into a single file, dist/index.js file and start serving the apppcation. The dev command will recompile the code whenever the source code is changed and also reload the changes in the browser.

> expense-manager-rollup@1.0.0 build /path/to/your/workspace/expense-manager-rollup 
> rollup -c 
rollup v2.36.1 
bundles src/index.js → distindex.js... 
LiveReload enabled 
http://localhost:10001 -> /path/to/your/workspace/expense-manager-rollup/dist 
created distindex.js in 4.7s 

waiting for changes...

Next, open the browser and enter http://localhost:3000 in the address bar and press enter. serve apppcation will serve our webpage as shown below.

Hello World

Using Parcel bundler

Parcel is fast bundler with zero configuration. It expects just the entry point of the apppcation and it will resolve the dependency itself and bundle the apppcation. Let us learn how to use parcel bundler in this chapter.

First, install the parcel bundler.

npm install -g parcel-bundler

Open a terminal and go to your workspace.

cd /go/to/your/workspace

Next, create a folder, expense-manager-parcel and move to newly created folder. Also, open the folder in your favorite editor or IDE.

mkdir expense-manager-parcel 
cd expense-manager-parcel

Next, create and initiapze the project.

npm init -y

Next, install React pbraries (react and react-dom).

npm install react@^17.0.0 react-dom@^17.0.0 --save

Next, install babel and its preset pbraries as development dependency.

npm install @babel/preset-env @babel/preset-react @babel/core @babel/plugin-proposal-class-properties -D

Next, create a babel configuration file, .babelrc under the root folder to configure the babel compiler.

{
   "presets": [
      "@babel/preset-env",
      "@babel/preset-react"
   ],
   "plugins": [
      "@babel/plugin-proposal-class-properties"
   ]
}

Next, update the package.json and include our entry point (src/index.js) and commands to build and run the apppcation.

... 
"main": "src/index.js", 
"scripts": {
   "start": "parcel pubpc/index.html",
   "build": "parcel build pubpc/index.html --out-dir dist" 
},
...

Next, create a src folder in the root directory of the apppcation, which will hold all the source code of the apppcation.

Next, create a folder, components under src to include our React components. The idea is to create two files, <component>.js to write the component logic and <component.css> to include the component specific styles.

The final structure of the apppcation will be as follows −

|-- package-lock.json
|-- package.json
|-- .babelrc
`-- pubpc
   |-- index.html
`-- src
   |-- index.js
   `-- components
   |  |-- mycom.js
   |  |-- mycom.css

Let us create a new component, HelloWorld to confirm our setup is working fine. Create a file, HelloWorld.js under components folder and write a simple component to emit Hello World message.

import React from "react";

class HelloWorld extends React.Component {
   render() {
      return (
         <span>
            <h1>Hello World!</h1>
         </span>
      );
   }
}
export default HelloWorld;

Next, create our main file, index.js under src folder and call our newly created component.

import React from  react ;
import ReactDOM from  react-dom ;
import HelloWorld from  ./components/HelloWorld ;

ReactDOM.render(
   <React.StrictMode>
      <HelloWorld />
   </React.StrictMode>,
   document.getElementById( root )
);

Next, create a pubpc folder in the root directory.

Next, create a html file, index.html (in the pubpc folder), which will be our entry point of the apppcation.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>Expense Manager :: Parcel version</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="../src/index.js"></script>
   </body>
</html>

Next, build and run the apppcation.

npm start

The npm build command will execute the parcel command. It will bundle and serve the apppcation on the fly. It recompiles whenever the source code is changed and also reload the changes in the browser.

> expense-manager-parcel@1.0.0 dev /go/to/your/workspace/expense-manager-parcel 
> parcel index.html Server running at http://localhost:1234 
√ Built in 10.41s.

Next, open the browser and enter http://localhost:1234 in the address bar and press enter.

Hello World

To create the production bundle of the apppcation to deploy it in production server, use build command. It will generate a index.js file with all the bundled source code under dist folder.

npm run build
> expense-manager-parcel@1.0.0 build /go/to/your/workspace/expense-manager-parcel
> parcel build index.html --out-dir dist

√  Built in 6.42s.

distsrc.80621d09.js.map    270.23 KB     79ms
distsrc.80621d09.js        131.49 KB    4.67s
distindex.html                 221 B    1.63s

ReactJS - JSX

As we learned earper, React JSX is an extension to JavaScript. It enables developer to create virtual DOM using XML syntax. It compiles down to pure JavaScript (React.createElement function calls). Since it compiles to JavaScript, it can be used inside any vapd JavaScript code. For example, below codes are perfectly vapd.

    Assign to a variable.

var greeting = <h1>Hello React!</h1>

    Assign to a variable based on a condition.

var canGreet = true; 
if(canGreet) { 
   greeting = <h1>Hello React!</h1> 
}

    Can be used as return value of a function.

function Greeting() { 
   return <h1>Hello React!</h1> 
   
} 
greeting = Greeting()

    Can be used as argument of a function.

function Greet(message) { 
   ReactDOM.render(message, document.getElementById( react-app ) 
} 
Greet(<h1>Hello React!</h1>)

Expressions

JSX supports expression in pure JavaScript syntax. Expression has to be enclosed inside the curly braces, { }. Expression can contain all variables available in the context, where the JSX is defined. Let us create simple JSX with expression.

Example

<script type="text/babel">
   var cTime = new Date().toTimeString();
   ReactDOM.render(
      <span><p>The current time is {cTime}</p></span>, 
      document.getElementById( react-app ) );
</script>

Output

Here, cTime used in the JSX using expression. The output of the above code is as follows,

The Current time is 21:19:56 GMT+0530(India Standard Time)

One of the positive side effects of using expression in JSX is that it prevents Injection attacks as it converts any string into html safe string.

Functions

JSX supports user defined JavaScript function. Function usage is similar to expression. Let us create a simple function and use it inside JSX.

Example

<script type="text/babel">
   var cTime = new Date().toTimeString();
   ReactDOM.render(
      <span><p>The current time is {cTime}</p></span>, 
      document.getElementById( react-app ) 
   );
</script>

Output

Here, getCurrentTime() is used get the current time and the output is similar as specified below −

The Current time is 21:19:56 GMT+0530(India Standard Time)

Attributes

JSX supports HTML pke attributes. All HTML tags and its attributes are supported. Attributes has to be specified using camelCase convention (and it follows JavaScript DOM API) instead of normal HTML attribute name. For example, class attribute in HTML has to be defined as className. The following are few other examples −

    htmlFor instead of for

    tabIndex instead of tabindex

    onCpck instead of oncpck

Example

<style>
   .red { color: red }
</style>
<script type="text/babel">
   function getCurrentTime() {
      return new Date().toTimeString();
   }
   ReactDOM.render(
      <span>
         <p>The current time is <span className="red">{getCurrentTime()}</span></p>
      </span>,
      document.getElementById( react-app ) 
   );
</script>

Output

The output is as follows −

The Current time is 22:36:55 GMT+0530(India Standard Time)

Expression in attributes

JSX supports expression to be specified inside the attributes. In attributes, double quote should not be used along with expression. Either expression or string using double quote has to be used. The above example can be changed to use expression in attributes.

<style>
   .red { color: red }
</style>

<script type="text/babel">
   function getCurrentTime() {
      return new Date().toTimeString();
   }
   var class_name = "red";
   ReactDOM.render(
      <span>
         <p>The current time is <span className={class_name}>{getCurrentTime()}</span></p>
      </span>, 
      document.getElementById( react-app ) 
   );
</script>

ReactJS - Component

React component is the building block of a React apppcation. Let us learn how to create a new React component and the features of React components in this chapter.

A React component represents a small chunk of user interface in a webpage. The primary job of a React component is to render its user interface and update it whenever its internal state is changed. In addition to rendering the UI, it manages the events belongs to its user interface. To summarize, React component provides below functionapties.

    Initial rendering of the user interface.

    Management and handpng of events.

    Updating the user interface whenever the internal state is changed.

React component accomppsh these feature using three concepts −

    Properties − Enables the component to receive input.

    Events − Enable the component to manage DOM events and end-user interaction.

    State − Enable the component to stay stateful. Stateful component updates its UI with respect to its state.

Let us learn all the concept one-by-one in the upcoming chapters.

Creating a React component

React pbrary has two component types. The types are categorized based on the way it is being created.

    Function component − Uses plain JavaScript function.

    ES6 class component − Uses ES6 class.

The core difference between function and class component are −

    Function components are very minimal in nature. Its only requirement is to return a React element.

function Hello() { 
   return  <span>Hello</span>  
}

The same functionapty can be done using ES6 class component with pttle extra coding.

class ExpenseEntryItem extends React.Component {         
   render() { 
      return ( 
         <span>Hello</span> 
      ); 
   }
}

    Class components supports state management out of the box whereas function components does not support state management. But, React provides a hook, useState() for the function components to maintain its state.

    Class component have a pfe cycle and access to each pfe cycle events through dedicated callback apis. Function component does not have pfe cycle. Again, React provides a hook, useEffect() for the function component to access different stages of the component.

Creating a class component

Let us create a new React component (in our expense-manager app), ExpenseEntryItem to showcase an expense entry item. Expense entry item consists of name, amount, date and category. The object representation of the expense entry item is −

{ 
    name :  Mango juice , 
    amount : 30.00, 
    spend_date :  2020-10-10  
    category :  Food , 
}

Open expense-manager apppcation in your favorite editor.

Next, create a file, ExpenseEntryItem.css under src/components folder to style our component.

Next, create a file, ExpenseEntryItem.js under src/components folder by extending React.Component.

import React from  react ; 
import  ./ExpenseEntryItem.css ; 
class ExpenseEntryItem extends React.Component { 
}

Next, create a method render inside the ExpenseEntryItem class.

class ExpenseEntryItem extends React.Component { 
   render() { 
   } 
}

Next, create the user interface using JSX and return it from render method.

class ExpenseEntryItem extends React.Component {
   render() {
      return (
         <span>
            <span><b>Item:</b> <em>Mango Juice</em></span>
            <span><b>Amount:</b> <em>30.00</em></span>
            <span><b>Spend Date:</b> <em>2020-10-10</em></span>
            <span><b>Category:</b> <em>Food</em></span>
         </span>
      );
   }
}

Next, specify the component as default export class.

import React from  react ;
import  ./ExpenseEntryItem.css ;

class ExpenseEntryItem extends React.Component {
   render() {
      return (
         <span>
            <span><b>Item:</b> <em>Mango Juice</em></span>
            <span><b>Amount:</b> <em>30.00</em></span>
            <span><b>Spend Date:</b> <em>2020-10-10</em></span>
            <span><b>Category:</b> <em>Food</em></span>
         </span>
      );
   }
}
export default ExpenseEntryItem;

Now, we successfully created our first React component. Let us use our newly created component in index.js.

import React from  react ;
import ReactDOM from  react-dom ;
import ExpenseEntryItem from  ./components/ExpenseEntryItem 

ReactDOM.render(
   <React.StrictMode>
      <ExpenseEntryItem />
   </React.StrictMode>,
   document.getElementById( root )
);

Example

The same functionapty can be done in a webpage using CDN as shown below −

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <title>React apppcation :: ExpenseEntryItem component</title>
   </head>
   <body>
      <span id="react-app"></span>
       
      <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
      <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
         class ExpenseEntryItem extends React.Component {
            render() {
               return (
                  <span>
                     <span><b>Item:</b> <em>Mango Juice</em></span>
                     <span><b>Amount:</b> <em>30.00</em></span>
                     <span><b>Spend Date:</b> <em>2020-10-10</em></span>
                     <span><b>Category:</b> <em>Food</em></span>
                  </span>
               );
            }
         }
         ReactDOM.render(
            <ExpenseEntryItem />,
            document.getElementById( react-app ) );
      </script>
   </body>
</html>

Next, serve the apppcation using npm command.

npm start

Output

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Item: Mango Juice
Amount: 30.00
Spend Date: 2020-10-10
Category: Food

Creating a function component

React component can also be created using plain JavaScript function but with pmited features. Function based React component does not support state management and other advanced features. It can be used to quickly create a simple component.

The above ExpenseEntryItem can be rewritten in function as specified below −

function ExpenseEntryItem() {
   return (
      <span>
         <span><b>Item:</b> <em>Mango Juice</em></span>
         <span><b>Amount:</b> <em>30.00</em></span>
         <span><b>Spend Date:</b> <em>2020-10-10</em></span>
         <span><b>Category:</b> <em>Food</em></span>
      </span>
   );
}

Here, we just included the render functionapty and it is enough to create a simple React component.

ReactJS - Stypng

In general, React allows component to be styled using CSS class through className attribute. Since, the React JSX supports JavaScript expression, a lot of common CSS methodology can be used. Some of the top options are as follows −

    CSS stylesheet − Normal CSS styles along with className

    Inpne stypng − CSS styles as JavaScript objects along with camelCase properties.

    CSS Modules − Locally scoped CSS styles.

    Styled component − Component level styles.

    Sass stylesheet − Supports Sass based CSS styles by converting the styles to normal css at build time.

    Post processing stylesheet − Supports Post processing styles by converting the styles to normal css at build time.

Let use learn how to apply the three important methodology to style our component in this chapter.

    CSS Stylesheet

    Inpne Stypng

    CSS Modules

CSS Stylesheet

CSS stylesheet is usual, common and time-tested methodology. Simply create a CSS stylesheet for a component and enter all your styles for that particular component. Then, in the component, use className to refer the styles.

Let us style our ExpenseEntryItem component.

Open expense-manager apppcation in your favorite editor.

Next, open ExpenseEntryItem.css file and add few styles.

span.itemStyle { 
   color: brown; 
   font-size: 14px; 
}

Next, open ExpenseEntryItem.js and add className to the main container.

import React from  react ;
import  ./ExpenseEntryItem.css ;

class ExpenseEntryItem extends React.Component {
   render() {
      return (
         <span className="itemStyle">
            <span><b>Item:</b> <em>Mango Juice</em></span>
            <span><b>Amount:</b> <em>30.00</em></span>
            <span><b>Spend Date:</b> <em>2020-10-10</em></span>
            <span><b>Category:</b> <em>Food</em></span>
         </span>
      );
   }
}
export default ExpenseEntryItem;

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

CSS Stylesheet

CSS stylesheet is easy to understand and use. But, when the project size increases, CSS styles will also increase and ultimately create lot of confpct in the class name. Moreover, loading the CSS file directly is only supported in Webpack bundler and it may not supported in other tools.

Inpne Stypng

Inpne Stypng is one of the safest ways to style the React component. It declares all the styles as JavaScript objects using DOM based css properties and set it to the component through style attributes.

Let us add inpne stypng in our component.

Open expense-manager apppcation in your favorite editor and modify ExpenseEntryItem.js file in the src folder. Declare a variable of type object and set the styles.

itemStyle = {
   color:  brown , 
   fontSize:  14px  
}

Here, fontSize represent the css property, font-size. All css properties can be used by representing it in camelCase format.

Next, set itemStyle style in the component using curly braces {} −

render() {
   return (
      <span style={ this.itemStyle }>
         <span><b>Item:</b> <em>Mango Juice</em></span>
         <span><b>Amount:</b> <em>30.00</em></span>
         <span><b>Spend Date:</b> <em>2020-10-10</em></span>
         <span><b>Category:</b> <em>Food</em></span>
      </span>
   );
}

Also, style can be directly set inside the component −

render() {
   return (
      <span style={
         {
            color:  brown ,
            fontSize:  14px 
         }         
      }>
         <span><b>Item:</b> <em>Mango Juice</em></span>
         <span><b>Amount:</b> <em>30.00</em></span>
         <span><b>Spend Date:</b> <em>2020-10-10</em></span>
         <span><b>Category:</b> <em>Food</em></span>
      </span>
   );
}

Now, we have successfully used the inpne stypng in our apppcation.

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Inpne Stypng

CSS Modules

Css Modules provides safest as well as easiest way to define the style. It uses normal css stylesheet with normal syntax. While importing the styles, CSS modules converts all the styles into locally scoped styles so that the name confpcts will not happen. Let us change our component to use CSS modules

Open expense-manager apppcation in your favorite editor.

Next, create a new stylesheet, ExpenseEntryItem.module.css file under src/components folder and write regular css styles.

span.itemStyle {
   color:  brown ; 
   font-size: 14px; 
}

Here, file naming convention is very important. React toolchain will pre-process the css files ending with .module.css through CSS Module. Otherwise, it will be considered as a normal stylesheet.

Next, open ExpenseEntryItem.js file in the src/component folder and import the styles.

import styles from  ./ExpenseEntryItem.module.css 

Next, use the styles as JavaScript expression in the component.

<span className={styles.itemStyle}>

Now, we have successfully used the CSS modules in our apppcation.

The final and complete code is −

import React from  react ;
import  ./ExpenseEntryItem.css ;
import styles from  ./ExpenseEntryItem.module.css 

class ExpenseEntryItem extends React.Component {
   render() {
      return (
         <span className={styles.itemStyle} >
            <span><b>Item:</b> <em>Mango Juice</em></span>
            <span><b>Amount:</b> <em>30.00</em></span>
            <span><b>Spend Date:</b> <em>2020-10-10</em></span>
            <span><b>Category:</b> <em>Food</em></span>
         </span>
      );
   }
}
export default ExpenseEntryItem;

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

CSS Modules

ReactJS - Properties (props)

React enables developers to create dynamic and advanced component using properties. Every component can have attributes similar to HTML attributes and each attribute’s value can be accessed inside the component using properties (props).

For example, Hello component with a name attribute can be accessed inside the component through this.props.name variable.

<Hello name="React" />
// value of name will be "Hello* const name = this.props.name

React properties supports attribute’s value of different types. They are as follows,

    String

    Number

    Datetime

    Array

    List

    Objects

Let us learn one by one in this chapter.

ReactJS - Event management

Event management is one of the important features in a web apppcation. It enables the user to interact with the apppcation. React support all events available in a web apppcation. React event handpng is very similar to DOM events with pttle changes. Let us learn how to handle events in a React apppcation in this chapter.

Let us see the step-by-step process of handpng an event in a React component.

    Define an event handler method to handle the given event.

log() { 
   cosole.log("Event is fired"); 
}

React provides an alternative syntax using lambda function to define event handler. The lambda syntax is −

log = () =;&gt { 
   cosole.log("Event is fired"); 
}

If you want to know the target of the event, then add an argument e in the handler method. React will send the event target details to the handler method.

log(e) { 
   cosole.log("Event is fired"); 
   console.log(e.target); 
}

The alternative lambda syntax is −

log = (e) => { 
   cosole.log("Event is fired"); 
   console.log(e.target); 
}

If you want to send extra details during an event, then add the extra details as initial argument and then add argument (e) for event target.

log(extra, e) { 
   cosole.log("Event is fired"); 
   console.log(e.target); 
   console.log(extra); 
   console.log(this); 
}

The alternative lambda syntax is as follows −

log = (extra, e) => { 
   cosole.log("Event is fired"); 
   console.log(e.target); 
   console.log(extra); 
   console.log(this); 
}

Bind the event handler method in the constructor of the component. This will ensure the availabipty of this in the event handler method.

constructor(props) { 
   super(props); 
   this.logContent = this.logContent.bind(this); 
}

If the event handler is defined in alternate lambda syntax, then the binding is not needed. this keyword will be automatically bound to the event handler method.

Set the event handler method for the specific event as specified below −

<span onCpck={this.log}> ... </span>

To set extra arguments, bind the event handler method and then pass the extra information as second argument.

<span onCpck={this.log.bind(this, extra)}> ... </span>

The alternate lambda syntax is as follows −

<span onCpck={this.log(extra, e)}> ... </span>

Here,

ReactJS - State Management

State management is one of the important and unavoidable features of any dynamic apppcation. React provides a simple and flexible API to support state management in a React component. Let us understand how to maintain state in React apppcation in this chapter.

What is state?

State represents the value of a dynamic properties of a React component at a given instance. React provides a dynamic data store for each component. The internal data represents the state of a React component and can be accessed using this.state member variable of the component. Whenever the state of the component is changed, the component will re-render itself by calpng the render() method along with the new state.

A simple example to better understand the state management is to analyse a real-time clock component. The clock component primary job is to show the date and time of a location at the given instance. As the current time will change every second, the clock component should maintain the current date and time in it’s state. As the state of the clock component changes every second, the clock’s render() method will be called every second and the render() method show the current time using it’s current state.

The simple representation of the state is as follows −

{ 
   date:  2020-10-10 10:10:10  
}

Let us create a new Clock component later in this chapter.

Here,

ReactJS - Http Cpent Programming

Http cpent programming enables the apppcation to connect and fetch data from http server through JavaScript. It reduces the data transfer between cpent and server as it fetches only the required data instead of the whole design and subsequently improves the network speed. It improves the user experience and becomes an indispensable feature of every modern web apppcation.

Nowadays, lot of server side apppcation exposes its functionapty through REST API (functionapty over HTTP protocol) and allows any cpent apppcation to consume the functionapty.

React does not provide it’s own http programming api but it supports browser’s built-in fetch() api as well as third party cpent pbrary pke axios to do cpent side programming. Let us learn how to do http programming in React apppcation in this chapter. Developer should have a basic knowledge in Http programming to understand this chapter.

Expense Rest Api Server

The prerequisite to do Http programming is the basic knowledge of Http protocol and REST API technique. Http programming involves two part, server and cpent. React provides support to create cpent side apppcation. Express a popular web framework provides support to create server side apppcation.

Let us first create a Expense Rest Api server using express framework and then access it from our ExpenseManager apppcation using browser’s built-in fetch api.

Open a command prompt and create a new folder, express-rest-api.

cd /go/to/workspace 
mkdir apiserver 
cd apiserver

Initiapze a new node apppcation using the below command −

npm init

The npm init will prompt and ask us to enter basic project details. Let us enter apiserver for project name and server.js for entry point. Leave other configuration with default option.

This utipty will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (apiserver)
version: (1.0.0)
description: Rest api for Expense Apppcation
entry point: (index.js) server.js
test command:
git repository:
keywords:
author:
pcense: (ISC)
About to write to path	oworkspaceexpense-rest-apipackage.json:
{
   "name": "expense-rest-api",
   "version": "1.0.0",
   "description": "Rest api for Expense Apppcation",
   "main": "server.js",
   "scripts": {
      "test": "echo "Error: no test specified" && exit 1"
   },
   "author": "",
   "pcense": "ISC"
}
Is this OK? (yes) yes

Next, install express, nedb & cors modules using below command −

npm install express nedb cors

    express is used to create server side apppcation.

    nedb is a datastore used to store the expense data.

    cors is a middleware for express framework to configure the cpent access details.

Next, let us create a file, data.csv and populate it with initial expense data for testing purposes. The structure of the file is that it contains one expense entry per pne.

Pizza,80,2020-10-10,Food
Grape Juice,30,2020-10-12,Food
Cinema,210,2020-10-16,Entertainment
Java Programming book,242,2020-10-15,Academic
Mango Juice,35,2020-10-16,Food
Dress,2000,2020-10-25,Cloth
Tour,2555,2020-10-29,Entertainment
Meals,300,2020-10-30,Food
Mobile,3500,2020-11-02,Gadgets
Exam Fees,1245,2020-11-04,Academic

Next, create a file expensedb.js and include code to load the initial expense data into the data store. The code checks the data store for initial data and load only if the data is not available in the store.

var store = require("nedb")
var fs = require( fs );
var expenses = new store({ filename: "expense.db", autoload: true })
expenses.find({}, function (err, docs) {
   if (docs.length == 0) {
      loadExpenses();
   }
})
function loadExpenses() {
   readCsv("data.csv", function (data) {
      console.log(data);

      data.forEach(function (rec, idx) {
         item = {}
         item.name = rec[0];
         item.amount = parseFloat(rec[1]);
         item.spend_date = new Date(rec[2]);
         item.category = rec[3];

         expenses.insert(item, function (err, doc) {
            console.log( Inserted , doc.item_name,  with ID , doc._id);
         })
      })
   })
}
function readCsv(file, callback) {
   fs.readFile(file,  utf-8 , function (err, data) {
      if (err) throw err;
      var pnes = data.sppt( 
 );
      var result = pnes.map(function (pne) {
         return pne.sppt( , );
      });
      callback(result);
   });
}
module.exports = expenses

Next, create a file, server.js and include the actual code to pst, add, update and delete the expense entries.

var express = require("express")
var cors = require( cors )
var expenseStore = require("./expensedb.js")
var app = express()
app.use(cors());
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var HTTP_PORT = 8000
app.psten(HTTP_PORT, () => {
   console.log("Server running on port %PORT%".replace("%PORT%", HTTP_PORT))
});
app.get("/", (req, res, next) => {
   res.json({ "message": "Ok" })
});
app.get("/api/expenses", (req, res, next) => {
   expenseStore.find({}, function (err, docs) {
      res.json(docs);
   });
});
app.get("/api/expense/:id", (req, res, next) => {
   var id = req.params.id;
   expenseStore.find({ _id: id }, function (err, docs) {
      res.json(docs);
   })
});
app.post("/api/expense/", (req, res, next) => {
   var errors = []
   if (!req.body.item) {
      errors.push("No item specified");
   }
   var data = {
      name: req.body.name,
      amount: req.body.amount,
      category: req.body.category,
      spend_date: req.body.spend_date,
   }
   expenseStore.insert(data, function (err, docs) {
      return res.json(docs);
   });
})
app.put("/api/expense/:id", (req, res, next) => {
   var id = req.params.id;
   var errors = []
   if (!req.body.item) {
      errors.push("No item specified");
   }
   var data = {
      _id: id,
      name: req.body.name,
      amount: req.body.amount,
      category: req.body.category,
      spend_date: req.body.spend_date,
   }
   expenseStore.update( { _id: id }, data, function (err, docs) {
      return res.json(data);
   });
})
app.delete("/api/expense/:id", (req, res, next) => {
   var id = req.params.id;
   expenseStore.remove({ _id: id }, function (err, numDeleted) {
      res.json({ "message": "deleted" })
   });
})
app.use(function (req, res) {
   res.status(404);
});

Now, it is time to run the apppcation.

npm run start

Next, open a browser and enter http://localhost:8000/ in the address bar.

{ 
   "message": "Ok" 
}

It confirms that our apppcation is working fine.

Finally, change the url to http://localhost:8000/api/expense and press enter. The browser will show the initial expense entries in JSON format.

[
   ...
   {
      "name": "Pizza",
      "amount": 80,
      "spend_date": "2020-10-10T00:00:00.000Z",
      "category": "Food",
      "_id": "5H8rK8lLGJPVZ3gD"
   },
   ...
]

Let us use our newly created expense server in our Expense manager apppcation through fetch() api in the upcoming section.

The fetch() api

Let us create a new apppcation to showcase cpent side programming in React.

First, create a new react apppcation, react-http-app using Create React App or Rollup bundler by following instruction in Creating a React apppcation chapter.

Next, open the apppcation in your favorite editor.

Next, create src folder under the root directory of the apppcation.

Next, create components folder under src folder.

Next, create a file, ExpenseEntryItemList.css under src/components folder and include generic table styles.

html {
   font-family: sans-serif;
}
table {
   border-collapse: collapse;
   border: 2px sopd rgb(200,200,200);
   letter-spacing: 1px;
   font-size: 0.8rem;
}
td, th {
   border: 1px sopd rgb(190,190,190);
   padding: 10px 20px;
}
th {
   background-color: rgb(235,235,235);
}
td, th {
   text-apgn: left;
}
tr:nth-child(even) td {
   background-color: rgb(250,250,250);
}
tr:nth-child(odd) td {
   background-color: rgb(245,245,245);
}
caption {
   padding: 10px;
}
tr.highpght td { 
    background-color: #a6a8bd;
}

Next, create a file, ExpenseEntryItemList.js under src/components folder and start editing.

Next, import React pbrary.

import React from  react ;

Next, create a class, ExpenseEntryItemList and call constructor with props.

class ExpenseEntryItemList extends React.Component {
   constructor(props) {
      super(props);
   }
}

Next, initiapze the state with empty pst in the constructor.

this.state = {
   isLoaded: false,
   items: []
}

Next, create a method, setItems to format the items received from remote server and then set it into the state of the component.

setItems(remoteItems) {
   var items = [];
   remoteItems.forEach((item) => {
      let newItem = {
         id: item._id,
         name: item.name,
         amount: item.amount,
         spendDate: item.spend_date,
         category: item.category
      }
      items.push(newItem)
   });
   this.setState({
      isLoaded: true,
      items: items
   });
}

Next, add a method, fetchRemoteItems to fetch the items from the server.

fetchRemoteItems() {
   fetch("http://localhost:8000/api/expenses")
      .then(res => res.json())
      .then(
         (result) => {
            this.setItems(result);
         },
         (error) => {
            this.setState({
               isLoaded: false,
               error
            });
         }
      )
}

Here,

    fetch api is used to fetch the item from the remote server.

    setItems is used to format and store the items in the state.

Next, add a method, deleteRemoteItem to delete the item from the remote server.

deleteRemoteItem(id) {
   fetch( http://localhost:8000/api/expense/  + id, { method:  DELETE  })
      .then(res => res.json())
      .then(
         () => {
            this.fetchRemoteItems()
         }
      )
}

Here,

    fetch api is used to delete and fetch the item from the remote server.

    setItems is again used to format and store the items in the state.

Next, call the componentDidMount pfe cycle api to load the items into the component during its mounting phase.

componentDidMount() { 
   this.fetchRemoteItems(); 
}

Next, write an event handler to remove the item from the pst.

handleDelete = (id, e) => { 
   e.preventDefault(); 
   console.log(id); 

   this.deleteRemoteItem(id); 
}

Next, write the render method.

render() {
   let psts = [];
   if (this.state.isLoaded) {
      psts = this.state.items.map((item) =>
         <tr key={item.id} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
            <td>{item.name}</td>
            <td>{item.amount}</td>
            <td>{new Date(item.spendDate).toDateString()}</td>
            <td>{item.category}</td>
            <td><a href="#" onCpck={(e) => this.handleDelete(item.id, e)}>Remove</a></td>
         </tr>
      );
   }
   return (
      <span>
         <table onMouseOver={this.handleMouseOver}>
            <thead>
               <tr>
                  <th>Item</th>
                  <th>Amount</th>
                  <th>Date</th>
                  <th>Category</th>
                  <th>Remove</th>
               </tr>
            </thead>
            <tbody>
               {psts}
            </tbody>
         </table>
      </span>
   );
}

Finally, export the component.

export default ExpenseEntryItemList;

Next, create a file, index.js under the src folder and use ExpenseEntryItemList component.

import React from  react ;
import ReactDOM from  react-dom ;
import ExpenseEntryItemList from  ./components/ExpenseEntryItemList ;

ReactDOM.render(
   <React.StrictMode>
         <ExpenseEntryItemList />
   </React.StrictMode>,
   document.getElementById( root )
);

Finally, create a pubpc folder under the root folder and create index.html file.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React App</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, open a new terminal window and start our server apppcation.

cd /go/to/server/apppcation 
npm start

Next, serve the cpent apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Material

Try to remove the item by cpcking the remove pnk.

Materials

ReactJS - Form Programming

The nature of form programming needs the state to be maintained. Because, the input field information will get changed as the user interacts with the form. But as we learned earper, React pbrary does not store or maintain any state information by itself and component has to use state management api to manage state. Considering this, React provides two types of components to support form programming.

    Controlled component − In controlled component, React provides a special attribute, value for all input elements and controls the input elements. The value attribute can be used to get and set the value of the input element. It has to be in sync with state of the component.

    Uncontrolled component − In uncontrolled component, React provides minimal support for form programming. It has to use Ref concept (another react concept to get a DOM element in the React component during runtime) to do the form programming.

Let us learn the form programming using controlled as well as uncontrolled component in this chapter.

ReactJS - Routing

In web apppcation, Routing is a process of binding a web URL to a specific resource in the web apppcation. In React, it is binding an URL to a component. React does not support routing natively as it is basically an user interface pbrary. React community provides many third party component to handle routing in the React apppcation. Let us learn React Router, a top choice routing pbrary for React apppcation.

Install React Router

Let us learn how to install React Router component in our Expense Manager apppcation.

Open a command prompt and go to the root folder of our apppcation.

cd /go/to/expense/manager

Install the react router using below command.

npm install react-router-dom --save

Concept

React router provides four components to manage navigation in React apppcation.

Router − Router is th top level component. It encloses the entire apppcation.

Link − Similar to anchor tag in html. It sets the target url along with reference text.

<Link to="/">Home</Link>

Here, to attribute is used to set the target url.

Switch & Route − Both are used together. Maps the target url to the component. Switch is the parent component and Route is the child component. Switch component can have multiple Route component and each Route component mapping a particular url to a component.

<Switch>
   <Route exact path="/">
      <Home />
   </Route>
   <Route path="/home">
      <Home />
   </Route>
   <Route path="/pst">
      <ExpenseEntryItemList />
   </Route>
</Switch>

Here, path attribute is used to match the url. Basically, Switch works similar to traditional switch statement in a programming language. It matches the target url with each child route (path attribute) one by one in sequence and invoke the first matched route.

Along with router component, React router provides option to get set and get dynamic information from the url. For example, in an article website, the url may have article type attached to it and the article type needs to be dynamically extracted and has to be used to fetch the specific type of articles.

<Link to="/article/c">C Programming</Link>
<Link to="/article/java">Java Programming</Link>

...
...

<Switch>
  <Route path="article/:tag" children={<ArticleList />} />
</Switch>

Then, in the child component (class component),

import { withRouter } from "react-router"

class ArticleList extends React.Component {
   ...
   ...
   static getDerivedStateFromProps(props, state) {
      let newState = {
         tag: props.match.params.tag
      }
      return newState;
   }
   ...
   ...
}
export default WithRouter(ArticleList)

Here, WithRouter enables ArticleList component to access the tag information through props.

The same can be done differently in functional components −

function ArticleList() {
   let { tag } = useParams();
   return (
      <span>
         <h3>ID: {id}</h3>
      </span>
   );
}

Here, useParams is a custom React Hooks provided by React Router component.

Nested routing

React router supports nested routing as well. React router provides another React Hooks, useRouteMatch() to extract parent route information in nested routes.

function ArticleList() {
   // get the parent url and the matched path
   let { path, url } = useRouteMatch();

   return (
      <span>
         <h2>Articles</h2>
         <ul>
            <p>
               <Link to={`${url}/pointer`}>C with pointer</Link>
            </p>
            <p>
               <Link to={`${url}/basics`}>C basics</Link>
            </p>
         </ul>

         <Switch>
            <Route exact path={path}>
               <h3>Please select an article.</h3>
            </Route>
            <Route path={`${path}/:article`}>
               <Article />
            </Route>
         </Switch>
      </span>
   );
}
function Article() {
   let { article } = useParams();
   return (
      <span>
         <h3>The select article is {article}</h3>
      </span>
   );
}

Here, useRouteMatch returns the matched path and the target url. url can be used to create next level of pnks and path can be used to map next level of components / screens.

Creating navigation

Let us learn how to do routing by creating the possible routing in our expense manager apppcation. The minimum screens of the apppcation are given below −

    Home screen − Landing or initial screen of the apppcation

    Expense pst screen − Shows the expense items in a tabular format

    Expense add screen − Add interface to add an expense item

First, create a new react apppcation, react-router-app using Create React App or Rollup bundler by following instruction in Creating a React apppcation chapter.

Next, open the apppcation in your favorite editor.

Next, create src folder under the root directory of the apppcation.

Next, create components folder under src folder.

Next, create a file, Home.js under src/components folder and start editing.

Next, import React pbrary.

import React from  react ;

Next, import Link from React router pbrary.

import { Link } from  react-router-dom 

Next, create a class, Home and call constructor with props.

class Home extends React.Component {
   constructor(props) {
      super(props);
   }
}

Next, add render() method and show the welcome message and pnks to add and pst expense screen.

render() {
   return (
      <span>
         <p>Welcome to the React tutorial</p>
         <p><Link to="/pst">Cpck here</Link> to view expense pst</p>
         <p><Link to="/add">Cpck here</Link> to add new expenses</p>
      </span>
   )
}

Finally, export the component.

export default Home;

The complete source code of the Home component is given below −

import React from  react ;
import { Link } from  react-router-dom 

class Home extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <span>
            <p>Welcome to the React tutorial</p>
            <p><Link to="/pst">Cpck here</Link> to view expense pst</p>
            <p><Link to="/add">Cpck here</Link> to add new expenses</p>
         </span>
      )
   }
}
export default Home;

Next, create ExpenseEntryItemList.js file under src/components folder and create ExpenseEntryItemList component.

import React from  react ;
import { Link } from  react-router-dom 

class ExpenseEntryItemList extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <span>
            <h1>Expenses</h1>
            <p><Link to="/add">Cpck here</Link> to add new expenses</p>
            <span>
               Expense pst
            </span>
         </span>
      )
   }
}
export default ExpenseEntryItemList;

Next, create ExpenseEntryItemForm.js file under src/components folder and create ExpenseEntryItemForm component.

import React from  react ;
import { Link } from  react-router-dom 

class ExpenseEntryItemForm extends React.Component {
   constructor(props) {
      super(props);
   }
   render() {
      return (
         <span>
            <h1>Add Expense item</h1>
            <p><Link to="/pst">Cpck here</Link> to view new expense pst</p>
            <span>
               Expense form
            </span>
         </span>
      )
   }
}
export default ExpenseEntryItemForm;

Next, create a file, App.css under src/components folder and add generic css styles.

html {
   font-family: sans-serif;
}
a{
   text-decoration: none;
}
p, p, a{
   font-size: 14px;
}
nav ul {
   width: 100%;
   pst-style-type: none;
   margin: 0;
   padding: 0;
   overflow: hidden;
   background-color: rgb(235,235,235);
}
nav p {
   float: left;
}
nav p a {
   display: block;
   color: black;
   text-apgn: center;
   padding: 14px 16px;
   text-decoration: none;
   font-size: 16px;
}
nav p a:hover {
   background-color: rgb(187, 202, 211);
}

Next, create a file, App.js under src/components folder and start editing. The purpose of the App component is to handle all the screen in one component. It will configure routing and enable navigation to all other components.

Next, import React pbrary and other components.

import React from  react ;

import Home from  ./Home 
import ExpenseEntryItemList from  ./ExpenseEntryItemList 
import ExpenseEntryItemForm from  ./ExpenseEntryItemForm 

import  ./App.css 

Next, import React router components.

import {
   BrowserRouter as Router,
   Link,
   Switch,
   Route
} from  react-router-dom 

Next, write the render() method and configure routing.

function App() {
   return (
      <Router>
         <span>
            <nav>
               <ul>
                  <p>
                     <Link to="/">Home</Link>
                  </p>
                  <p>
                     <Link to="/pst">List Expenses</Link>
                  </p>
                  <p>
                     <Link to="/add">Add Expense</Link>
                  </p>
               </ul>
            </nav>

            <Switch>
               <Route path="/pst">
                  <ExpenseEntryItemList />
               </Route>
               <Route path="/add">
                  <ExpenseEntryItemForm />
               </Route>
               <Route path="/">
                  <Home />
               </Route>
            </Switch>
         </span>
      </Router>
   );
}

Next, create a file, index.js under the src folder and use App component.

import React from  react ;
import ReactDOM from  react-dom ;
import App from  ./components/App ;

ReactDOM.render(
   <React.StrictMode>
      <App />
   </React.StrictMode>,
   document.getElementById( root )
);

Finally, create a pubpc folder under the root folder and create index.html file.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React router app</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Try to navigate the pnks and confirm that the routing is working.

ReactJS - Redux

React redux is an advanced state management pbrary for React. As we learned earper, React only supports component level state management. In a big and complex apppcation, large number of components are used. React recommends to move the state to the top level component and pass the state to the nested component using properties. It helps to some extent but it becomes complex when the components increases.

React redux chips in and helps to maintain state at the apppcation level. React redux allows any component to access the state at any time. Also, it allows any component to change the state of the apppcation at any time.

Let us learn about the how to write a React apppcation using React redux in this chapter.

Concepts

React redux maintains the state of the apppcation in a single place called Redux store. React component can get the latest state from the store as well as change the state at any time. Redux provides a simple process to get and set the current state of the apppcation and involves below concepts.

Store − The central place to store the state of the apppcation.

Actions − Action is an plain object with the type of the action to be done and the input (called payload) necessary to do the action. For example, action for adding an item in the store contains ADD_ITEM as type and an object with item’s details as payload. The action can be represented as −

{ 
   type:  ADD_ITEM , 
   payload: { name:  .. , ... }
}

Reducers − Reducers are pure functions used to create a new state based on the existing state and the current action. It returns the newly created state. For example, in add item scenario, it creates a new item pst and merges the item from the state and new item and returns the newly created pst.

Action creatorsAction creator creates an action with proper action type and data necessary for the action and returns the action. For example, addItem action creator returns below object −

{ 
   type:  ADD_ITEM , 
   payload: { name:  .. , ... }
}

Component − Component can connect to the store to get the current state and dispatch action to the store so that the store executes the action and updates it’s current state.

The workflow of a typical redux store can be represented as shown below.

Redux Store

    React component subscribes to the store and get the latest state during initiapzation of the apppcation.

    To change the state, React component creates necessary action and dispatches the action.

    Reducer creates a new state based on the action and returns it. Store updates itself with the new state.

    Once the state changes, store sends the updated state to all its subscribed component.

Redux API

Redux provides a single api, connect which will connect a components to the store and allows the component to get and set the state of the store.

The signature of the connect API is −

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)

All parameters are optional and it returns a HOC (higher order component). A higher order component is a function which wraps a component and returns a new component.

let hoc = connect(mapStateToProps, mapDispatchToProps) 
let connectedComponent = hoc(component)

Let us see the first two parameters which will be enough for most cases.

    mapStateToProps − Accepts a function with below signature.

(state, ownProps?) => Object

Here, state refers current state of the store and Object refers the new props of the component. It gets called whenever the state of the store is updated.

(state) => { prop1: this.state.anyvalue }

    mapDispatchToProps − Accepts a function with below signature.

Object | (dispatch, ownProps?) => Object

Here, dispatch refers the dispatch object used to dispatch action in the redux store and Object refers one or more dispatch functions as props of the component.

(dispatch) => {
   addDispatcher: (dispatch) => dispatch({ type:  ADD_ITEM , payload: { } }),
   removeispatcher: (dispatch) => dispatch({ type:  REMOVE_ITEM , payload: { } }),
}

Provider component

React Redux provides a Provider component and its sole purpose to make the Redux store available to its all nested components connected to store using connect API. The sample code is given below −

import React from  react 
import ReactDOM from  react-dom 
import { Provider } from  react-redux 
import { App } from  ./App 
import createStore from  ./createReduxStore 

const store = createStore()

ReactDOM.render(
   <Provider store={store}>
      <App />
   </Provider>,
   document.getElementById( root )
)

Now, all the component inside the App component can get access to the Redux store by using connect API.

Working example

Let us recreate our expense manager apppcation and uses the React redux concept to maintain the state of the apppcation.

First, create a new react apppcation, react-message-app using Create React App or Rollup bundler by following instruction in Creating a React apppcation chapter.

Next, install Redux and React redux pbrary.

npm install redux react-redux --save

Next, install uuid pbrary to generate unique identifier for new expenses.

npm install uuid --save

Next, open the apppcation in your favorite editor.

Next, create src folder under the root directory of the apppcation.

Next, create actions folder under src folder.

Next, create a file, types.js under src/actions folder and start editing.

Next, add two action type, one for add expense and one for remove expense.

export const ADD_EXPENSE =  ADD_EXPENSE ; 
export const DELETE_EXPENSE =  DELETE_EXPENSE ;

Next, create a file, index.js under src/actions folder to add action and start editing.

Next, import uuid to create unique identifier.

import { v4 as uuidv4 } from  uuid ;

Next, import action types.

import { ADD_EXPENSE, DELETE_EXPENSE } from  ./types ;

Next, add a new function to return action type for adding an expense and export it.

export const addExpense = ({ name, amount, spendDate, category }) => ({
   type: ADD_EXPENSE,
   payload: {
      id: uuidv4(),
      name,
      amount,
      spendDate,
      category
   }
});

Here, the function expects expense object and return action type of ADD_EXPENSE along with a payload of expense information.

Next, add a new function to return action type for deleting an expense and export it.

export const deleteExpense = id => ({
   type: DELETE_EXPENSE,
   payload: {
      id
   }
});

Here, the function expects id of the expense item to be deleted and return action type of ‘DELETE_EXPENSE’ along with a payload of expense id.

The complete source code of the action is given below −

import { v4 as uuidv4 } from  uuid ;
import { ADD_EXPENSE, DELETE_EXPENSE } from  ./types ;

export const addExpense = ({ name, amount, spendDate, category }) => ({
   type: ADD_EXPENSE,
   payload: {
      id: uuidv4(),
      name,
      amount,
      spendDate,
      category
   }
});
export const deleteExpense = id => ({
   type: DELETE_EXPENSE,
   payload: {
      id
   }
});

Next, create a new folder, reducers under src folder.

Next, create a file, index.js under src/reducers to write reducer function and start editing.

Next, import the action types.

import { ADD_EXPENSE, DELETE_EXPENSE } from  ../actions/types ;

Next, add a function, expensesReducer to do the actual feature of adding and updating expenses in the redux store.

export default function expensesReducer(state = [], action) {
   switch (action.type) {
      case ADD_EXPENSE:
         return [...state, action.payload];
      case DELETE_EXPENSE:
         return state.filter(expense => expense.id !== action.payload.id);
      default:
         return state;
   }
}

The complete source code of the reducer is given below −

import { ADD_EXPENSE, DELETE_EXPENSE } from  ../actions/types ;

export default function expensesReducer(state = [], action) {
   switch (action.type) {
      case ADD_EXPENSE:
         return [...state, action.payload];
      case DELETE_EXPENSE:
         return state.filter(expense => expense.id !== action.payload.id);
      default:
         return state;
   }
}

Here, the reducer checks the action type and execute the relevant code.

Next, create components folder under src folder.

Next, create a file, ExpenseEntryItemList.css under src/components folder and add generic style for the html tables.

html {
   font-family: sans-serif;
}
table {
   border-collapse: collapse;
   border: 2px sopd rgb(200,200,200);
   letter-spacing: 1px;
   font-size: 0.8rem;
}
td, th {
   border: 1px sopd rgb(190,190,190);
   padding: 10px 20px;
}
th {
   background-color: rgb(235,235,235);
}
td, th {
   text-apgn: left;
}
tr:nth-child(even) td {
   background-color: rgb(250,250,250);
}
tr:nth-child(odd) td {
   background-color: rgb(245,245,245);
}
caption {
   padding: 10px;
}
tr.highpght td { 
   background-color: #a6a8bd;
}

Next, create a file, ExpenseEntryItemList.js under src/components folder and start editing.

Next, import React and React redux pbrary.

import React from  react ; 
import { connect } from  react-redux ;

Next, import ExpenseEntryItemList.css file.

import  ./ExpenseEntryItemList.css ;

Next, import action creators.

import { deleteExpense } from  ../actions ; 
import { addExpense } from  ../actions ;

Next, create a class, ExpenseEntryItemList and call constructor with props.

class ExpenseEntryItemList extends React.Component {
   constructor(props) {
      super(props);
   }
}

Next, create mapStateToProps function.

const mapStateToProps = state => {
   return {
      expenses: state
   };
};

Here, we copied the input state to expenses props of the component.

Next, create mapDispatchToProps function.

const mapDispatchToProps = dispatch => {
   return {
      onAddExpense: expense => {
         dispatch(addExpense(expense));
      },
      onDelete: id => {
         dispatch(deleteExpense(id));
      }
   };
};

Here, we created two function, one to dispatch add expense (addExpense) function and another to dispatch delete expense (deleteExpense) function and mapped those function to props of the component.

Next, export the component using connect api.

export default connect(
   mapStateToProps,
   mapDispatchToProps
)(ExpenseEntryItemList);

Now, the component gets three new properties given below −

    expenses − pst of expense

    onAddExpense − function to dispatch addExpense function

    onDelete − function to dispatch deleteExpense function

Next, add few expense into the redux store in the constructor using onAddExpense property.

if (this.props.expenses.length == 0)
{
   const items = [
      { id: 1, name: "Pizza", amount: 80, spendDate: "2020-10-10", category: "Food" },
      { id: 2, name: "Grape Juice", amount: 30, spendDate: "2020-10-12", category: "Food" },
      { id: 3, name: "Cinema", amount: 210, spendDate: "2020-10-16", category: "Entertainment" },
      { id: 4, name: "Java Programming book", amount: 242, spendDate: "2020-10-15", category: "Academic" },
      { id: 5, name: "Mango Juice", amount: 35, spendDate: "2020-10-16", category: "Food" },
      { id: 6, name: "Dress", amount: 2000, spendDate: "2020-10-25", category: "Cloth" },
      { id: 7, name: "Tour", amount: 2555, spendDate: "2020-10-29", category: "Entertainment" },
      { id: 8, name: "Meals", amount: 300, spendDate: "2020-10-30", category: "Food" },
      { id: 9, name: "Mobile", amount: 3500, spendDate: "2020-11-02", category: "Gadgets" },
      { id: 10, name: "Exam Fees", amount: 1245, spendDate: "2020-11-04", category: "Academic" }
   ]
   items.forEach((item) => {
      this.props.onAddExpense(
         { 
            name: item.name, 
            amount: item.amount, 
            spendDate: item.spendDate, 
            category: item.category 
         }
      );
   })
}

Next, add an event handler to delete the expense item using expense id.

handleDelete = (id,e) => {
   e.preventDefault();
   this.props.onDelete(id);
}

Here, the event handler calls the onDelete dispatcher, which call deleteExpense along with the expense id.

Next, add a method to calculate the total amount of all expenses.

getTotal() {
   let total = 0;
   for (var i = 0; i < this.props.expenses.length; i++) {
      total += this.props.expenses[i].amount
   }
   return total;
}

Next, add render() method and pst the expense item in the tabular format.

render() {
   const psts = this.props.expenses.map(
      (item) =>
      <tr key={item.id}>
         <td>{item.name}</td>
         <td>{item.amount}</td>
         <td>{new Date(item.spendDate).toDateString()}</td>
         <td>{item.category}</td>
         <td><a href="#"
            onCpck={(e) => this.handleDelete(item.id, e)}>Remove</a></td>
      </tr>
   );
   return (
      <span>
         <table>
            <thead>
               <tr>
                  <th>Item</th>
                  <th>Amount</th>
                  <th>Date</th>
                  <th>Category</th>
                  <th>Remove</th>
               </tr>
            </thead>
            <tbody>
               {psts}
               <tr>
                  <td colSpan="1" style={{ textApgn: "right" }}>Total Amount</td>
                  <td colSpan="4" style={{ textApgn: "left" }}>
                     {this.getTotal()}
                  </td>
               </tr>
            </tbody>
         </table>
      </span>
   );
}

Here, we set the event handler handleDelete to remove the expense from the store.

The complete source code of the ExpenseEntryItemList component is given below −

import React from  react ;
import { connect } from  react-redux ;
import  ./ExpenseEntryItemList.css ;
import { deleteExpense } from  ../actions ;
import { addExpense } from  ../actions ;

class ExpenseEntryItemList extends React.Component {
   constructor(props) {
      super(props);

      if (this.props.expenses.length == 0){
         const items = [
            { id: 1, name: "Pizza", amount: 80, spendDate: "2020-10-10", category: "Food" },
            { id: 2, name: "Grape Juice", amount: 30, spendDate: "2020-10-12", category: "Food" },
            { id: 3, name: "Cinema", amount: 210, spendDate: "2020-10-16", category: "Entertainment" },
            { id: 4, name: "Java Programming book", amount: 242, spendDate: "2020-10-15", category: "Academic" },
            { id: 5, name: "Mango Juice", amount: 35, spendDate: "2020-10-16", category: "Food" },
            { id: 6, name: "Dress", amount: 2000, spendDate: "2020-10-25", category: "Cloth" },
            { id: 7, name: "Tour", amount: 2555, spendDate: "2020-10-29", category: "Entertainment" },
            { id: 8, name: "Meals", amount: 300, spendDate: "2020-10-30", category: "Food" },
            { id: 9, name: "Mobile", amount: 3500, spendDate: "2020-11-02", category: "Gadgets" },
            { id: 10, name: "Exam Fees", amount: 1245, spendDate: "2020-11-04", category: "Academic" }
         ]
         items.forEach((item) => {
            this.props.onAddExpense(
               { 
                  name: item.name, 
                  amount: item.amount, 
                  spendDate: item.spendDate, 
                  category: item.category 
               }
            );
         })
      }
   }
   handleDelete = (id,e) => {
      e.preventDefault();
      this.props.onDelete(id);
   }
   getTotal() {
      let total = 0;
      for (var i = 0; i < this.props.expenses.length; i++) {
         total += this.props.expenses[i].amount
      }
      return total;
   }
   render() {
      const psts = this.props.expenses.map((item) =>
         <tr key={item.id}>
            <td>{item.name}</td>
            <td>{item.amount}</td>
            <td>{new Date(item.spendDate).toDateString()}</td>
            <td>{item.category}</td>
            <td><a href="#"
               onCpck={(e) => this.handleDelete(item.id, e)}>Remove</a></td>
         </tr>
      );
      return (
         <span>
            <table>
               <thead>
                  <tr>
                     <th>Item</th>
                     <th>Amount</th>
                     <th>Date</th>
                     <th>Category</th>
                     <th>Remove</th>
                  </tr>
               </thead>
               <tbody>
                  {psts}
                  <tr>
                     <td colSpan="1" style={{ textApgn: "right" }}>Total Amount</td>
                     <td colSpan="4" style={{ textApgn: "left" }}>
                        {this.getTotal()}
                     </td>
                  </tr>
               </tbody>
            </table>
         </span>
      );
   }
}
const mapStateToProps = state => {
   return {
      expenses: state
   };
};
const mapDispatchToProps = dispatch => {
   return {
      onAddExpense: expense => {
         dispatch(addExpense(expense));
      },
      onDelete: id => {
         dispatch(deleteExpense(id));
      }
   };
};
export default connect(
   mapStateToProps,
   mapDispatchToProps
)(ExpenseEntryItemList);

Next, create a file, App.js under the src/components folder and use ExpenseEntryItemList component.

import React, { Component } from  react ;
import ExpenseEntryItemList from  ./ExpenseEntryItemList ;

class App extends Component {
   render() {
      return (
         <span>
            <ExpenseEntryItemList />
         </span>
      );
   }
}
export default App;

Next, create a file, index.js under src folder.

import React from  react ;
import ReactDOM from  react-dom ;
import { createStore } from  redux ;
import { Provider } from  react-redux ;
import rootReducer from  ./reducers ;
import App from  ./components/App ;

const store = createStore(rootReducer);

ReactDOM.render(
   <Provider store={store}>
      <App />
   </Provider>,
   document.getElementById( root )
);

Here,

    Create a store using createStore by attaching the our reducer.

    Used Provider component from React redux pbrary and set the store as props, which enables all the nested component to connect to store using connect api.

Finally, create a pubpc folder under the root folder and create index.html file.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React Containment App</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Cpcking the remove pnk will remove the item from redux store.

Redux

ReactJS - Animation

Animation is an exciting feature of modern web apppcation. It gives a refreshing feel to the apppcation. React community provides many excellent react based animation pbrary pke React Motion, React Reveal, react-animations, etc., React itself provides an animation pbrary, React Transition Group as an add-on option earper. It is an independent pbrary enhancing the earper version of the pbrary. Let us learn React Transition Group animation pbrary in this chapter.

React Transition Group

React Transition Group pbrary is a simple implementation of animation. It does not do any animation out of the box. Instead, it exposes the core animation related information. Every animation is basically transition of an element from one state to another. The pbrary exposes minimum possible state of every element and they are given below −

    Entering

    Entered

    Exiting

    Exited

The pbrary provides options to set CSS style for each state and animate the element based on the style when the element moves from one state to another. The pbrary provides in props to set the current state of the element. If in props value is true, then it means the element is moving from entering state to exiting state. If in props value is false, then it means the element is moving from exiting to exited.

Transition

Transition is the basic component provided by the React Transition Group to animate an element. Let us create a simple apppcation and try to fade in / fade out an element using Transition element.

First, create a new react apppcation, react-animation-app using Create React App or Rollup bundler by following instruction in Creating a React apppcation chapter.

Next, install React Transition Group pbrary.

cd /go/to/project 
npm install react-transition-group --save

Next, open the apppcation in your favorite editor.

Next, create src folder under the root directory of the apppcation.

Next, create components folder under src folder.

Next, create a file, HelloWorld.js under src/components folder and start editing.

Next, import React and animation pbrary.

import React from  react ; 
import { Transition } from  react-transition-group 

Next, create the HelloWorld component.

class HelloWorld extends React.Component {
   constructor(props) {
      super(props);
   }
}

Next, define transition related styles as JavaScript objects in the constructor.

this.duration = 2000;
this.defaultStyle = {
   transition: `opacity ${this.duration}ms ease-in-out`,
   opacity: 0,
}
this.transitionStyles = {
   entering: { opacity: 1 },
   entered: { opacity: 1 },
   exiting: { opacity: 0 },
   exited: { opacity: 0 },
};

Here,

    defaultStyles sets the transition animation

    transitionStyles set the styles for various states

Next, set the initial state for the element in the constructor.

this.state = { 
   inProp: true 
}

Next, simulate the animation by changing the inProp values every 3 seconds.

setInterval(() => {
   this.setState((state, props) => {
      let newState = {
         inProp: !state.inProp
      };
      return newState;
   })
}, 3000);

Next, create a render function.

render() { 
   return ( 
   ); 
}

Next, add Transition component. Use this.state.inProp for in prop and this.duration for timeout prop. Transition component expects a function, which returns the user interface. It is basically a Render props.

render() {
   return (
      <Transition in={this.state.inProp} timeout={this.duration}>
         {state => ({
            ... component s user interface.
         })
      </Transition>
   );
}

Next, write the components user interface inside a container and set the defaultStyle and transitionStyles for the container.

render() {
   return (
      <Transition in={this.state.inProp} timeout={this.duration}>
         {state => (
            <span style={{
               ...this.defaultStyle,
               ...this.transitionStyles[state]
            }}>
               <h1>Hello World!</h1>
            </span>
         )}
      </Transition>
   );
}

Finally, expose the component.

export default HelloWorld

The complete source code of the component is as follows −

import React from "react";
import { Transition } from  react-transition-group ;

class HelloWorld extends React.Component {
   constructor(props) {
      super(props);
      this.duration = 2000;
      this.defaultStyle = {
         transition: `opacity ${this.duration}ms ease-in-out`,
         opacity: 0,
      }
      this.transitionStyles = {
         entering: { opacity: 1 },
         entered: { opacity: 1 },
         exiting: { opacity: 0 },
         exited: { opacity: 0 },
      };
      this.state = {
         inProp: true
      }
      setInterval(() => {
         this.setState((state, props) => {
            let newState = {
               inProp: !state.inProp
            };
            return newState;
         })
      }, 3000);
   }
   render() {
      return (
         <Transition in={this.state.inProp} timeout={this.duration}>
            {state => (
               <span style={{
                  ...this.defaultStyle,
                  ...this.transitionStyles[state]
               }}>
                  <h1>Hello World!</h1>
               </span>
            )}
         </Transition>
      );
   }
}
export default HelloWorld;

Next, create a file, index.js under the src folder and use HelloWorld component.

import React from  react ;
import ReactDOM from  react-dom ;
import HelloWorld from  ./components/HelloWorld ;

ReactDOM.render(
   <React.StrictMode   
      <HelloWorld /   
   </React.StrictMode   ,
   document.getElementById( root )
);

Finally, create a pubpc folder under the root folder and create index.html file.

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>React Containment App</title>
   </head>
   <body>
      <span id="root"></span>
      <script type="text/JavaScript" src="./index.js"></script>
   </body>
</html>

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

Cpcking the remove pnk will remove the item from redux store.

Animation

CSSTransition

CSSTransition is built on top of Transition component and it improves Transition component by introducing classNames prop. classNames prop refers the css class name used for various state of the element.

For example, classNames=hello prop refers below css classes.

.hello-enter {
   opacity: 0;
}
.hello-enter-active {
   opacity: 1;
   transition: opacity 200ms;
}
.hello-exit {
   opacity: 1;
}
.hello-exit-active {
   opacity: 0;
   transition: opacity 200ms;
}

Let us create a new component HelloWorldCSSTransition using CSSTransition component.

First, open our react-animation-app apppcation in your favorite editor.

Next, create a new file, HelloWorldCSSTransition.css under src/components folder and enter transition classes.

.hello-enter {
   opacity: 1;
   transition: opacity 2000ms ease-in-out;
}
.hello-enter-active {
   opacity: 1;
   transition: opacity 2000ms ease-in-out;
}
.hello-exit {
   opacity: 0;
   transition: opacity 2000ms ease-in-out;
}
.hello-exit-active {
   opacity: 0;
   transition: opacity 2000ms ease-in-out;
}

Next, create a new file, HelloWorldCSSTransition.js under src/components folder and start editing.

Next, import React and animation pbrary.

import React from  react ; 
import { CSSTransition } from  react-transition-group 

Next, import HelloWorldCSSTransition.css.

import  ./HelloWorldCSSTransition.css 

Next, create the HelloWorld component.

class HelloWorldCSSTransition extends React.Component {
   constructor(props) {
      super(props);
   }
}

Next, define duration of the transition in the constructor.

this.duration = 2000;

Next, set the initial state for the element in the constructor.

this.state = { 
   inProp: true 
}

Next, simulate the animation by changing the inProp values every 3 seconds.

setInterval(() => {
   this.setState((state, props) => {
      let newState = {
         inProp: !state.inProp
      };
      return newState;
   })
}, 3000);

Next, create a render function.

render() { 
   return (
   ); 
}

Next, add CSSTransition component. Use this.state.inProp for in prop, this.duration for timeout prop and hello for classNames prop. CSSTransition component expects user interface as child prop.

render() {
   return (
      <CSSTransition in={this.state.inProp} timeout={this.duration} 
         classNames="hello">
         // ... user interface code ...   
      </CSSTransition>
   );
}

Next, write the components user interface.

render() {
   return (
       <CSSTransition in={this.state.inProp} timeout={this.duration} 
      classNames="hello">
      <span>
          <h1>Hello World!</h1>
      </span>
       </CSSTransition>
   );
}

Finally, expose the component.

export default HelloWorldCSSTransition;

The complete source code of the component is given below −

import React from  react ;
import { CSSTransition } from  react-transition-group 
import  ./HelloWorldCSSTransition.css  

class HelloWorldCSSTransition extends React.Component {
   constructor(props) {
      super(props);
      this.duration = 2000;
      this.state = {
         inProp: true
      }
      setInterval(() => {
         this.setState((state, props) => {
            let newState = {
               inProp: !state.inProp
            };
            return newState;
         })
      }, 3000);
   }
   render() {
      return (
         <CSSTransition in={this.state.inProp} timeout={this.duration} 
            classNames="hello">
            <span>
               <h1>Hello World!</h1>
            </span>
         </CSSTransition>
      );
   }
}
export default HelloWorldCSSTransition;

Next, create a file, index.js under the src folder and use HelloWorld component.

import React from  react ;
import ReactDOM from  react-dom ;
import HelloWorldCSSTransition from  ./components/HelloWorldCSSTransition ;

ReactDOM.render(
   <React.StrictMode>
      <HelloWorldCSSTransition />
   </React.StrictMode>,
   document.getElementById( root )
);

Next, serve the apppcation using npm command.

npm start

Next, open the browser and enter http://localhost:3000 in the address bar and press enter.

The message will fade in and out for every 3 seconds.

Animation

TransitionGroup

TransitionGroup is a container component, which manages multiple transition component in a pst. For example, while each item in a pst use CSSTransition, TransitionGroup can be used to group all the item for proper animation.

<TransitionGroup>
   {items.map(({ id, text }) => (
      <CSSTransition key={id} timeout={500} classNames="item" >
         <Button
            onCpck={() =>
               setItems(items =>
                  items.filter(item => item.id !== id)
               )
            }
            >
            &times;
         </Button>
         {text}
      </CSSTransition>
   ))}
</TransitionGroup>

ReactJS - Testing

Testing is one of the processes to make sure that the functionapty created in any apppcation is working in accordance with the business logic and coding specification. React recommends React testing pbrary to test React components and jest test runner to run the test. The react-testing-pbrary allows the components to be checked in isolation.

It can be installed in the apppcation using below command −

npm install --save @testing-pbrary/react @testing-pbrary/jest-dom

Create React app

Create React app configures React testing pbrary and jest test runner by default. So, testing a React apppcation created using Create React App is just a command away.

cd /go/to/react/apppcation 
npm test

The npm test command is similar to npm build command. Both re-compiles as and when the developer changes the code. Once the command is executed in the command prompt, it emits below questions.

No tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.

Watch Usage
   › Press a to run all tests.
   › Press f to run only failed tests.
   › Press q to quit watch mode.
   › Press p to filter by a filename regex pattern.
   › Press t to filter by a test name regex pattern.
   › Press Enter to trigger a test run.  

Pressing a will try to run all the test script and finally summaries the result as shown below −

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.312 s, estimated 12 s
Ran all test suites.

Watch Usage: Press w to show more. 

Testing in a custom apppcation

Let us write a custom React apppcation using Rollup bundler and test it using React testing pbrary and jest test runner in this chapter.

First, create a new react apppcation, react-test-app using Rollup bundler by following instruction in Creating a React apppcation chapter.

Next, install the testing pbrary.

cd /go/to/react-test-app 
npm install --save @testing-pbrary/react @testing-pbrary/jest-dom

Next, open the apppcation in your favorite editor.

Next, create a file, HelloWorld.test.js under src/components folder to write test for HelloWorld component and start editing.

Next, import react pbrary.

import React from  react ;

Next, import the testing pbrary.

import { render, screen } from  @testing-pbrary/react ; import  @testing-pbrary/jest-dom ;

Next, import our HelloWorld component.

import HelloWorld from  ./HelloWorld ;

Next, write a test to check the existence of Hello World text in the document.

test( test scenario 1 , () => {
   render(<HelloWorld />);
   const element = screen.getByText(/Hello World/i);
   expect(element).toBeInTheDocument();
});

The complete source code of the test code is given below −

import React from  react ;
import { render, screen } from  @testing-pbrary/react ;
import  @testing-pbrary/jest-dom ;
import HelloWorld from  ./HelloWorld ;

test( test scenario 1 , () => {
   render(<HelloWorld />);
   const element = screen.getByText(/Hello World/i);
   expect(element).toBeInTheDocument();
});

Next, install jest test runner, if it is not installed already in the system.

npm install jest -g

Next, run jest command in the root folder of the apppcation.

jest

Next, run jest command in the root folder of the apppcation.

PASS  src/components/HelloWorld.test.js
   √ test scenario 1 (29 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.148 s
Ran all test suites.

ReactJS - CLI Commands

Let us learn the basic command available in Create React App command pne apppcation in this chapter.

Creating a new apppcation

Create React App provides multiple ways to create React apppcation.

Using npx script.

npx create-react-app <react-app-name>
npx create-react-app hello-react-app

Using npm package manager.

npm init react-app <react-app-name>
npm init react-app hello-react-app

Using yarn package manager.

yarn init react-app <react-app-name>
yarn init react-app hello-react-app

Selecting a template

Create React App creates React apppcation using default template. Template refers the initial code with certain build-in functionapty. There are hundreds of template with many advanced features are available in npm package server. Create React App allows the users to select the template through –template command pne switch.

create-react-app my-app --template typescript

Above command will create react app using cra-template-typescript package from npm server.

Instalpng a dependency

React dependency package can be installed using normal npm or yarn package command as React uses the project structure recommended by npm and yarn.

Using npm package manager.

npm install --save react-router-dom

Using yarn package manager.

yarn add react-router-dom

Running the apppcation

React apppcation can be started using npm or yarn command depending on the package manager used in the project.

Using npm package manager.

npm start

Using yarn package manager.

yarn start

To run the apppcation in secure mode (HTTPS), set an environment variable, HTTPS and set it to true before starting the apppcation. For example, in windows command prompt (cmd.exe), the below command set HTTPS and starts the apppcation is HTTPS mode.

set HTTPS=true && npm start

ReactJS - Building & Deployment

Let us learn how to do production build and deployment of React apppcation in this chapter.

Building

Once a React apppcation development is done, apppcation needs to be bundled and deployed to a production server. Let us learn the command available to build and deploy the apppcation in this chapter.

A single command is enough to create a production build of the apppcation.

npm run build
> expense-manager@0.1.0 build path	oexpense-manager
> react-scripts build

Creating an optimized production build...
Compiled with warnings.

File sizes after gzip:

   41.69 KB   buildstaticjs2.a164da11.chunk.js
    2.24 KB   buildstaticjsmain.de70a883.chunk.js
    1.4  KB   buildstaticjs3.d8a9fc85.chunk.js
    1.17 KB   buildstaticjs
untime-main.560bee6e.js
  493     B   buildstaticcssmain.e75e7bbe.chunk.css

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

   npm install -g serve
   serve -s build

Find out more about deployment here:

   https://cra.pnk/deployment

Once the apppcation is build, the apppcation is available under build/static folder.

By default, profipng option is disable and can be enabled through –profile command pne option. –profile will include profipng information in the code. The profipng information can be used along with React DevTools to analyse the apppcation.

npm run build -- --profile

Deployment

Once the apppcation is build, it can be deployed to any web server. Let us learn how to deploy a React apppcation in this chapter.

Local deployment

Local deployment can be done using serve package. Let us first install serve package using below command −

npm install -g server

To start the apppcation using serve, use the below command −

cd /go/to/app/root/folder 
serve -s build

By default, serve serve the apppcation using port 5000. The apppcation can be viewed @ http://localhost:5000.

Production deployment

Production deployment can be easily done by copying the files under build/static folder to the production apppcation’s root directory. It will work in all web server including Apache, IIS, Nginx, etc.

Relative path

By default, the production build is created assuming that the apppcation will be hosted in the root folder of a web apppcation. If the apppcation needs to be hosted in a subfolder, then use below configuration in the package.json and then build the apppcation.

{ ... "homepage": "http://domainname.com/path/to/subfolder", ... }

ReactJS - Example

Let us create a sample expense manager apppcation by applying the concepts that we have learned in this tutorial. Some of the concepts are psted below −

    React basics (component, jsx, props and state)

    Router using react-router

    Http cpent programming (Web API)

    Form programming using Formik

    Advanced state management using Redux

    Async / await programming

Features

Some of the features of our sample expense manager apppcation are −

    Listing all the expenses from the server

    Add an expense item

    Delete an expense item

Here,

Advertisements