Mar 28, 2020

Textual description of firstImageUrl

ReactJS (HTTP/AJAX): Asynchronous Interaction between React application and Server (REST API with axions)

React application interaction with server to fetch data and submitting data to server is very common for any enterprise web application. Like any application react application requires HTTP Library to interact with server. We have HTTP library available some are promise based and some are callback based. Fetch and Axios are promised based HTTP library and Superagent is callback based HTTP library.

In this post I will use Axios for executing HTTP methods like GET and POST. In order to simply server side setup I have used Firebase Realtime Database. Firebase deals with JSON data and persist it in tree structure.

HTTP call in React component life cycle: componenetDidMount() is right place from where HTTP methods are executed with precaution do not update state as it will trigger re-rendering cycle and HTTP call be executed in infinite loop.

Prerequisite

1. Install and setup axios
2. Setup Firebase real time database & sample data setup

Install axios
$ npm install axios

Firebase setup: Create a sample project at Firebase(Spark mode is free). I have created project "react-devinline". Under database tab -> create Realtime Database "devinlineaction". Firebase generates URL https://devinlineaction.firebaseio.com/ which act as end point to access data from Firebase realtime database.

Under Rules tab update read and write access. It makes data access without auth and prevents error like "Failed to load resource: the server responded with a status of 401 (Unauthorized)"
{
  "rules": {
    ".read": true,
    ".write": true
  }
}. 

Import below JSON data in Firebase database devinlineaction
 {
  "orders": [
    {
      "orderNo": "3330047777379",
       "status": "Delivered",
      "customerInfo": {
        "customerId": "832edb65-6ea2-40e4-bb07-8c3a2bacc159",
        "primaryContact": {
          "name": {
            "firstName": "Nikhil",
            "lastName": "Ranjan"
          },
          "phone": {
            "completeNumber": "408-660-5027"
          },
          "email": {
            "emailAddress": "nikhilranjan@email.com"
          }
        },
        "address": {
          "addressLineOne": "655 S Fair Oaks Avenue",
          "addressType": "RESIDENTIAL",
          "city": "Sunnyvale",
          "countryCode": "USA",
          "postalCode": "94086",
          "state": "CA"
        }
      },
      "orderLines": [
        {
          "productName": "Fujifilm Instax Mini 7S Instant Camera (with 10-pack film) - Light Blue",
          "lineno": 1,
          "orderedQty": {
            "unitOfMeasure": "EA",
            "measurementValue": 1
          },
          "unitPrice": {
            "currencyAmount": 125,
            "currencyUnit": "USD"
          }
        },
        {
          "productName": "Sumsung Monitor 45' ",
          "lineno": 1,
          "orderedQty": {
            "unitOfMeasure": "EA",
            "measurementValue": 1
          },
          "unitPrice": {
            "currencyAmount": 305,
            "currencyUnit": "USD"
          }
        },
        {
          "productName": "Wirelss mouse Dell-UQA765",
          "lineno": 1,
          "orderedQty": {
            "unitOfMeasure": "EA",
            "measurementValue": 2
          },
          "unitPrice": {
            "currencyAmount": 25,
            "currencyUnit": "USD"
          }
        }
      ]
    },
    {
      "orderNo": "3330047777380",
       "status": "Shipped",
      "customerInfo": {
        "customerId": "832edb65-6ea2-40e4-bb07-8c3a2bacc159",
        "primaryContact": {
          "name": {
            "firstName": "Nikhil",
            "lastName": "Ranjan"
          },
          "phone": {
            "completeNumber": "408-660-5027"
          },
          "email": {
            "emailAddress": "nikhilranjan@email.com"
          }
        },
        "address": {
          "addressLineOne": "655 S Fair Oaks Avenue",
          "addressType": "RESIDENTIAL",
          "city": "Sunnyvale",
          "countryCode": "USA",
          "postalCode": "94086",
          "state": "CA"
        }
      },
      "orderLines": [
        {
          "productName": "Purell Advanced - 8 fl Oz",
          "lineno": 1,
          "orderedQty": {
            "unitOfMeasure": "EA",
            "measurementValue": 1
          },
          "unitPrice": {
            "currencyAmount": 10,
            "currencyUnit": "USD"
          }
        },
        {
          "productName": "Mask-12 pc",
          "lineno": 1,
          "orderedQty": {
            "unitOfMeasure": "EA",
            "measurementValue": 1
          },
          "unitPrice": {
            "currencyAmount": 12,
            "currencyUnit": "USD"
          }
        }
      ]
    }
  ]
}

HTTP GET API using axios

Create a class based component "Orders.js" and a functional component "Order.js". Class based component Orders executes GET API and displays orders in UI using Order functional component.

[Orders.js]- Class based component which manages state. orderStatus fetches order# and status & using Order component data are displayed.

import React, { Component } from 'react';
import axios from 'axios';

import Order from './Order';

class Orders extends Component {
    state = {
        ordersStatus: [],
        error: false
    }

    deleteDataHandler = (_orderNo) => {  
    }

    componentDidMount() {
        let ordernoAndStatus = []
        axios.get('https://devinlineaction.firebaseio.com/orders.json' )
            .then(res => {
                const fetchedOrders = [];
                for (let key in res.data) {
                    let orderNo = res.data[key].orderNo;
                    let status = res.data[key].status;
                    ordernoAndStatus.push({orderNo,status})
                    fetchedOrders.push({
                        ...res.data[key],
                        id: key
                    });
                }
                this.setState({ordersStatus : ordernoAndStatus});
                console.log(fetchedOrders);
            })
            .catch(err => {
                this.setState({loading: false});
            });
            
    }

    render () {
        let orders = <p style={{textAlign: 'center'}}>
            Opps!! Something went wrong.</p>;
        if (!this.state.error) {
            orders = this.state.ordersStatus.map(orderStat => {
                return <Order 
                    key={orderStat.orderNo}
                    orderNo={orderStat.orderNo} 
                    status={orderStat.status}
                    deleteHandle=
                        {this.deleteDataHandler(orderStat.orderNo)} />;
            });
        }
        return (
            <div>
                <section>
                    <h1> Get API using axios: Orders status</h1>
                    {orders}
                </section>
            </div>
        );
    }
}

export default Orders;

[Order.js] - Order component is functional/presentational component to generate UI with order# and status. Based on status Cancel order button is displayed (if order is delivered -> button is not displayed)
import React from 'react';

const order = (props) => (
    <div>
            <h3>{props.orderNo}</h3>
            {props.status}
            {props.status !== 'Delivered' ? <div><button 
                style={{ background: '#f44336', 
                         border: 'none',
                         color: 'white',
                         padding: '8px 5px',
                         fontSize: '20px',
                         cursor:'pointer',
                         }} 
                onClick={props.deleteHandle}>Cancel Order</button></div> : null}
     <div style={{width: '700px',
                    margin:'auto',
                    height: '7px',
                    borderBottom: '1px solid black'}}></div>
     </div>
     
);

export default order;


[App.js]
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import Orders from './containers/Orders'
import NewOrder from './components/NewOrder';

class App extends Component {
  
  render() {
    console.log('[App.js] render() execution');
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>

        {/* Render Child component Checkout */}
        <Orders/>
        <NewOrder/>
      </div>
    );
  }

}

export default App;


Start server using command : $ npm start and open http://localhost:3000/.
UI displaying order# and status & Console displaying GET Response

HTTP POST API using axios

[NewOrder.js] - HTTP Post method is executed on clicking create new Order button.

import React, { Component } from 'react';
import axios from 'axios';

class NewOrder extends Component {
    postDataHandler = () => {
        const data = {
            "orderNo": "3330047777381",
            "status": "Processing",
            "customerInfo": {
              "customerId": "832edb65-6ea2-40e4-bb07-8c3a2bacc159",
              "primaryContact": {
                "name": {
                  "firstName": "Nikhil",
                  "lastName": "Ranjan"
                },
                "phone": {
                  "completeNumber": "408-660-5028"
                },
                "email": {
                  "emailAddress": "nikhilranjan@email.com"
                }
              },
              "address": {
                "addressLineOne": "655 S Fair Oaks Avenue",
                "addressType": "RESIDENTIAL",
                "city": "Sunnyvale",
                "countryCode": "USA",
                "postalCode": "94086",
                "state": "CA"
              }
            },
            "orderLines": [
              {
                "productName": 
                    "Garmin vivoactive 3 Black with Stainless Hardware",
                "lineno": 1,
                "orderedQty": {
                  "unitOfMeasure": "EA",
                  "measurementValue": 1
                },
                "unitPrice": {
                  "currencyAmount": 149,
                  "currencyUnit": "USD"
                }
              }
            ]
          };
        axios.post('https://devinlineaction.firebaseio.com/orders.json', data)
            .then(response => {
                console.log(response);
                alert("Order Placed successfully !!")
            });
    }

    render () {
        return (
            <div>
                <h1> Post using axios: Place new order</h1>
                <button 
                    style={{ background: '#008CBA', 
                         border: 'none',
                         color: 'white',
                         padding: '15px 32px',
                         fontSize: '20px',
                         cursor:'pointer',
                         }} 
                    onClick={this.postDataHandler}>Create new Order</button>
            </div>
        );
    }
}

export default NewOrder;

Successful execution server respond with status code = 200

After refreshing UI - 3 orders are displayed in UI and Firebase database can be validated for new record.
Axios HTTP library can be used to execute DELETE,HEAD and PUT methods. It provides flexibility to configure request sent to server and handle server response. Error handling is also supported with axios.
Textual description of firstImageUrl

React components and life cycle: Stateful and stateless, Class-based and functional component & Class component life cycle.

React component can be classified in two category: Class(or Container) based component and Functional (or presentational) component. Historically(before ReactVersion 16.8) class based component has been considered stateful component and functional component is stateless component. From React-16.8 functional component can manages state using React Hooks useState().

A good strategy for React application is to restrict state management with very few component (ideally class based) and presentational component should be dependent on props and it makes presentational component more reusable.

Class based and functional component: Class based and functional component can be differentiated in following ways.

1. Class and functional component Syntax: Class-based component extends Component and function component is represented as function.
Functional component 
import React from 'react';

const contact = (props) => (
  <div>
    <h1>{props.title}</h1>
  </div>
);

export default contact;
Class-based component 
import React, { Component } from 'react';
import './Checkout.css';

class Checkout extends Component {
    state = {
        loggedInCustomer: null,
        guestCustomer:null
    }
  render() {
    return (
      <div className="Checkout">
        {/* manages state of app...  */}
      </div>
    );
  }
}

export default Checkout;

2. State accessibility and life cycle hooks: Both class-based component and functional component(From react 16.8) can access state. But only class based component has life cycle hooks. Life cycle hooks provides ability to modify state before and after loading components.
  • Class-based component access state and props via "this" and 
  • Functional component access state using useState() and Properties using props.
Class-component accessing state and props:
this.state.property-1 
this.props.property-2


Class component life cycle

Component Create life cycle: Create component life cycle starts from constructor() and ends at componentDidMount() methods. Both constructor() and componentDidMount() are optional methods, render() method must be defined to full component creation cycle.
Sample App.js to demonstrate component create cycle:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Checkout from './containers/Checkout';

class App extends Component {
  /*Step-1: Constructor */
  constructor(props){
    super(props);
    console.log('[App.js] constuctor');
  }
  state = {
    orders:[
      { upc: '007410134707', productName: 
        'Fujifilm Instax Mini 7S Instant Camera', unitPrice: "210" },
      { upc: '007410134708', productName: 
      'Monitor 43 Inch', unitPrice: "340" }
    ]
  }

  /* Step-2: getDerivedStateFromProps */
  static getDerivedStateFromProps(props,state){
    console.log('[App.js] getDerivedStateFromProps', props,state);
    return state;
  }

  /* Step-3: Execute render method */
  render() {
    console.log('[App.js] render() execution');
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          My First React App !!
        </p>
        {/* Render Child component Checkout */}
        <Checkout/>
      </div>
    );
  }

  /* Step-4: Execute componentDidMount: 
             make HTTP call at this point.... */
 componentDidMount(){
  console.log('[App.js] componentDidMount execution');
 }
}

export default App;

Component creation journey with child component Checkout 
Component update life cycle: Update component life cycle is more complex and has additional states. Update component life cycle pays important role in improving performance of application.

import React, { Component } from 'react';

class Checkout extends Component {
    /*Step-1: getDerivedStateFromProps: This will throw warning when loaded as initial satte is empty */
    static getDerivedStateFromProps(props,state){
        console.log('[Checkout.js] getDerivedStateFromProps');
        return state;
    }
    /* Step-2: Should return boolean(true/false) based on some condition */
    shouldComponentUpdate(nextProps, nextState){
        console.log('[Checkout.js] shouldComponentUpdate');
        /* Shalllow comparision not deep */
        if(nextProps.orders !== this.props.orders)
            return true;
        return false;
    }
    
    state = {
        loggedInCustomer: null,
        guestCustomer:null
    }
  /* Step-3: */
  render() {
    console.log('[Checkout.js] render() execution');
    return (
      <div className="Checkout">
        {/* manages state of Checkout...  */}
      </div>
    );
  }

    /* Step-4: Used to some operation before componentDidUpdate like gettting scrolling co-ordinate. 
        Save some data before udpate state.*/
    getSnapshotBeforeUpdate(prevProps, prevState){
            console.log('[Checkout.js] getSnapshotBeforeUpdate');
        return {message:'Snapshot!!'};
    }
        
        
  /* Step-5: */
  componentDidUpdate(prevProps, prevState,snapshot){
    console.log('[Persons.js] componentDidUpdate');
    console.log(snapshot);
}
}

export default Checkout;

Functional component with useEffect and setState
: Functional component does not have life cycle as class based component. Functional component uses React hooks to update state & execute certain method on every load of functional component.

Mar 23, 2020

Textual description of firstImageUrl

Getting started with React Application : How to install and setup React Application

React(ReactJS) is a component based declarative JavaScript library for building user interfaces. It has been developed and maintained by Facebook and community. In this post I will use "create-react-app" tool to create ReactApp.

Prerequisite: I am using homebrew to install all required softwares. Install homebrew

Step-1. Install node.js:  node is required to run tool create-react-app which setup react app in single command. Install node.js using below command or download node.js.
m-c02z31rnlvdt:~ n0r0082$ brew install node
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> New Formulae
.....
......
==> Summary
🍺  /usr/local/Cellar/icu4c/64.2: 257 files, 69.2MB
==> Installing node
==> Downloading https://homebrew.bintray.com/bottles/node-13.5.0.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/59/59bfd67c59d4af7643a12d9?__gd
######################################################################## 100.0%
==> Pouring node-13.5.0.mojave.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> Summary
🍺  /usr/local/Cellar/node/13.5.0: 4,663 files, 59.1MB
==> Caveats
-----
-------
For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c/include"

==> node
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

Validate node installation
m-c02z31rnlvdt:~ n0r0082$ node -v
v13.5.0
m-c02z31rnlvdt:~ n0r0082$ npm -v
6.13.4
m-c02z31rnlvdt:~ n0r0082$ which node
/usr/local/bin/node

Step-2: Install create-react-app tool which has enriched with all required utility and packages to setup react application with just one single command. -g indicates tool installed globally so that it can be executed from anywhere.

m-c02z31rnlvdt:reactApp n0r0082$ sudo npm install create-react-app -g 
Password:
/usr/local/bin/create-react-app -> /usr/local/lib/node_modules/create-react-app/index.js
+ create-react-app@3.3.0
added 91 packages from 45 contributors in 13.17s

Step-3: Crate react application using above installed tool create-react-app. Application name is my-first-app. --scripts-version only enforce structure of project created not react version.
m-c02z31rnlvdt:Learing n0r0082$ create-react-app my-first-app --scripts-version 1.1.5

Creating a new React app in /Users/n0r0082/Learing/my-first-app.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts...

......
........

added 1383 packages from 748 contributors and audited 14828 packages in 69.561s

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

found 40 vulnerabilities (29 low, 5 moderate, 6 high)
  run `npm audit fix` to fix them, or `npm audit` for details

Success! Created my-first-app at /Users/n0r0082/Learing/my-first-app
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd my-first-app
  npm start

Happy hacking!


Step-4: Go to location where my-first-app has been created. Start server using npm start. Once server is started, open browser and hit URL http://localhost:3000/


m-c02z31rnlvdt:my-first-app n0r0082$ npm start 

> my-first-app@0.1.0 start /Users/n0r0082/Learning/my-first-app
> react-scripts start


Compiled successfully!

You can now view my-first-app in the browser.

  Local:            http://localhost:3000/
  On Your Network:  http://192.168.0.3:3000/

Note that the development build is not optimized.
To create a production build, use npm run build.

my-first-app structure in VStudio:

Open App.js and make some changes and immediately it will be reflected in UI.
Referencehttps://github.com/facebook/create-react-app

Mar 21, 2020

Textual description of firstImageUrl

JavaScript Array and its functions - map(), reduce() and filter()

JavaScript Array class is a global object that is used in the construction of arrays. Arrays are objects with additional methods and properties. Like Object Array can have indexed and non-index elements. Before discussing commonly used JS Array functions, let's see how Array is different from Object.

Create an array with two elements(or properties) : Two elements added to array are indexed element.

  let my_cart = ['Item1-Brush', 'Item2-Stove','Item3-Laptop']

Currently length of array my_cart is 3. Add to non-indexed element/properties to my_cart using dot & bracket notation.

 my_cart.nonIndexed_item4 = "Item4-Laptop"
 my_cart["nonIndexed_item5"] = "Item5-monitor"

After adding two non-indexed property length of Array my_cart is still 3. Why? - length property of array does not indicate how many elements are present in Array, length is numerically greater than the biggest array index.


How to find length of Array/total number of elements present in an array ? 
- Using Object.keys(my_cart).length

Array.prototype functions

Array.prototype.map() - Used to create a new array by passing a callback function. Callback is applied on every element in the array.
An array with numbers and fetch square of positive integers from the given array. Original array is not modified.
let numbers = [1, 2, 3, 4, 5]
let modifed_numbers = numbers.map(num => (num*num))
// modifed_numbers [1, 4, 9, 16, 25] //numbers [1, 2, 3, 4, 5]

Get a modified array of object using callback function
let check_out_items = [{
    item_id: 1001,
    quantity: 10,
    item_name: 'Apple',
    unit_price: .4
}, {
    item_id: 2001,
    quantity: 20,
    item_name: 'Orange',
    unit_price: .3
}, {
    item_id: 3001,
    quantity: 5,
    item_name: 'mango',
    unit_price: .7
}]
//print check_out_items
0: {item_id: 1001, quantity: 10, item_name: "Apple", unit_price: 0.4}
1: {item_id: 2001, quantity: 20, item_name: "Orange", unit_price: 0.3}
2: {item_id: 3001, quantity: 5, item_name: "mango", unit_price: 0.7}

let check_out_price = check_out_items.map(item => {
    let item_price = {}
    item_price[item.item_name] = (item.quantity * item.unit_price)
    return item_price
})
//print check_out_price
0: {Apple: 4}
1: {Orange: 6}
2: {mango: 3.5}

Use .map() method should be only used when modified array need to re-used, otherwise .forEach() will be right choice to iterate all array elements and perform operation. 

Array.prototype.reduce()
- reduce() method executes a reducer function on each element of the array and resulting in a single output value. Consider above array check_out_price and apply reduce method find total price need to be paid at checkout.
Sample reduce() function:
function (accumulator, currentValue) {
  return accumulator + currentValue
}, initialValue

let check_out_price = check_out_items.map(item => {
   return (item.quantity * item.unit_price)
})

// console.log(check_out_price) [4, 6, 3.5]

let total_price = check_out_price.reduce(function (accumulator, currentValue) {
    return accumulator + currentValue
}, 0)

//console.log(total_price) 13.5

Reduce function can be applied to an array with an initial Value or without initial Value. If initialValue is not provided, reduce() will execute the callback function starting at index 1, skipping the first index. If initialValue is provided, it will start at index 0.

Array.prototype.filter() - filter() method creates a new array with all elements that pass the test implemented by the callback function.
let input = [4, 5, 6, 8, 9, 12, 17];
//console.log(input) [4, 6, 8, 12]
let filtered_input = input.filter(num =>; num %2 ==0)
// let filtered_input = input.filter(function(num){return num %2 ==0})

//console.log(filtered_input) [4, 6, 8, 12]