Learn React step by step, building a simple demo application.

React core concepts

  1. Components: Components are the basic building blocks of React applications,  a react application can be broken into smaller parts which are basically component with specific features driven by state and props.
  2. JSX: It's an add-on to react which simplifies describing the UI of the application.  JSX is compiled to React elements for rendering.
  3. state: State in an application refers to the core application data which drives the dynamic application. 
  4. props: It's an immutable form of state which is used in child components. Used in nested components.

Environment Setup

  1. Make sure you have NodeJS installed, NPM a dependency manager which comes with NodeJS.
  2. Install a global module for creating react application which has all dependencies and React project template to quickly start with React application.

npm install create-react-app -g

 

E:\reactapp>create-react-app react-redux-demo

The above command will create a react application named react-redux-demo inside the reactapp folder.

To run the application navigate to the react-redux-demo folder and run the command

npm start

 

 Basic component example:

Update the index.js file inside the application with the mentioned below code:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// import App from './App';
import registerServiceWorker from './registerServiceWorker';

const RenderLinks = (props) => {
    return(
        <ul>
        {props.menus.map(menu => {
            return <li key={menu.link} style={{display:'inline-block',margin:'10px',padding:'10px'}}>
                      <a href={menu.link}>{menu.name}</a>
                  </li>
        })}
        </ul>
    )
}

class Menu extends React.Component{
    constructor(props){
        super(props);
        this.state ={
            menus:[
                {name:'Home',link:'/home'},
                {name:'Contact',link:'/contact'},
                {name:'Services',link:'/services'}
            ]
        }
    }

    render(){
        return(
            <div>
              <RenderLinks menus={this.state.menus} />
            </div>
        )
    }
}

ReactDOM.render(<Menu />, document.getElementById('root'));
registerServiceWorker();

 

The above code creates a Menu component using the standard class-based approach which provides useful lifecycle methods of the component. The lifecycle methods are available to our component since we are extending a special class from React core library React.Component. Will explore the lifecycle methods in a different blog post.

Let's try to understand the Menu component which creates a simple menu with 3 items.

#22 initialize the component with a state having menus as an array of objects with properties name and link used to generate the link.

#31  is a special lifecycle method which renders the UI elements to the browser with some internal optimization achieved using virtual DOM.

#34 makes use of child component RenderLinks and is defined as a pure component which has no access to state and accesses the state properties using props passed from the parent component.

#11 used javascript native map function to generate the menu using the object properties. It's an immutable function since it returns a new copy of array based on the body implementation.

 

Refer below post for custom implementation of map or filter function.

http://www.learnwebtechs.com/2018/05/26/an-introduction-to-functional-programming-in-javascript

Note: JSX evaluates javascript code inside { }

 

#40 finally the component is rendered on the DOM using the element id root defined in the index.html inside the public folder.

Finally, let's build the demo application which is a simple application with username and message form fields to display it on the UI and later deleting it by clicking on it.

Update the App.js file with the mentioned below code to see the example project.

 

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

class App extends Component {

  constructor(props){
    super(props);
    this.state = {
      username:"",
      message:"",
      messageList: []
    }
  }

  onUsernameChange = (event) => {
   event.preventDefault();
   let username = event.target.value;
   this.setState(() => {
     return {
       username: username
     }
   })
  } 

  onMessageChange = (event) => {
    event.preventDefault();
    let message = event.target.value;
    this.setState(() => {
      return {
        message: message
      }
    })
  }


  remove = (id) => {
    const updatedList = this.state.messageList.filter((message) => message.id != id);
    this.setState(() => {
      return {
        messageList: updatedList
      }
    })
  }

  
  onSubmit = (event) => {
    event.preventDefault();
    let message = this.state.message;
    let username = this.state.username;
    this.setState((prevState) =>{
      return {
        messageList: prevState.messageList.concat({message:message,username:username,id:Date.now()})
      }
    })
  }

  render() {
    return (
      <div className="wrapper">
        <form name="post" onSubmit={this.onSubmit}>
        <input style={{padding:'10px',margin:'10px',width:'70%',textAlign:'left'}}
         type="text" 
         placeholder="username" 
         name="username" value={this.state.username}
         onChange={this.onUsernameChange} /><br />

        <textarea style={{padding:'10px',margin:'10px',width:'70%',rows:'50',cols:'40',textAlign:'left'}} 
        placeholder="message"
        name="message" 
        value={this.state.message}
        onChange={this.onMessageChange}>
         </textarea><br />

         <input style={{padding:'10px',margin:'10px',backgroundColor:'orange',textAlign:'left'}}
          type="submit"
           value="Post" />
        </form>
        <div>
          {this.state.messageList.map((message) => {
            return <div style={{display:'inline-block',
            padding:'20px',cursor:'pointer', margin:'0 20px 20px 0',
             border:'1px solid black', width:'200px'}} key={message.id}
              onClick={() => this.remove(message.id)}>
              <p>Username: {message.username}</p>
              <p>Message: {message.message}</p>
            </div>
          })}
        </div>
      </div>
    );
  }
}

export default App;

 

Update index.js file to use App as a component.

 

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

 

Let's going through the App.js file to understand few other important concepts. 

#15 and #25 defines methods which binds the username and message property to the UI. This way of the binding property is called controlled components since UI element property value is in sync to state property.

#18 setProps is a special method used to update the state property so that with any change the UI is re-rendered.

Note: Don't set the property directly like this.state.message = "hello" 

 

#52 is used to populate messageList property using the concat method instead of push. Concat is an immutable function that created a new copy of the messageList.

#83 is used to bind the click handler to remove method with id as an argument,  function here is not immediately invoked because it wrapped as an anonymous function using es6 syntax.

Feel free to comment and share your views. Thanks for reading.