o7planning

ReactJS Events Tutorial with Examples

  1. ReactJS Events
  2. Event of Child Component 
  3. A complex example
In this lesson, I am going to guide you "How to use Events in ReactJS". There are also not a lot of differences when you use events in the ReactJS compared to using the events in the Javascript.
  • In the Javascript, you will handle events in a function while in the React you will handle the events in a method of Component.

1. ReactJS Events

React is an library based on Javascript, basically, not much different in handling events between ReactJS and Javascript. For the Javascript, when an event occurs, a function will be called to execute. But for the React, when an event occurs, a method of Component is called.
OK, first of all, please see a simple example:
onClick-example.html
class CurrentTime extends React.Component {
  constructor(props) {
    super(props);

    var now = new Date();
    this.state = {
      currentTime: now.toString()
    };
  }

  // A method of CurrentTime component
  refreshCurrentTime() {
    var now = new Date();
    this.setState({ currentTime: now.toString() });
  }
  render() {
    return (
      <div>
        <h4>Current Time:</h4>
        <p>{this.state.currentTime}</p>
        <button onClick={() => this.refreshCurrentTime()}>
          Refresh Current Time
        </button>
      </div>
    );
  }
}

// Render
ReactDOM.render(<CurrentTime />, document.getElementById("currenttime1"));
onClick-example.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS Event</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
      <style>
         #currenttime1 {
         border:1px solid blue;
         padding: 5px;
         margin-top: 20px;
         }
      </style>
   </head>
   <body>
      <h3>ReactJS Event: onClick</h3>

      <div id="currenttime1"></div>

      <script src="onClick-example.jsx" type="text/babel"></script>

   </body>
</html>
Arrow Function
With the Javascript ES6 syntax, you can create an arrow function, which is very short and easy-to-understand:
** arrow function **
// Normal function with parameters
var myfunc = function(param1, param2)  {
   // Statements
};

// Arrow function with parameters.
var arrfunc = (param1, param2) => {
   // Statements
};


// Normal function without paramters.
var myfunc2 = function( )  {
   // Statements
};

// Arrow function without parameters.
var arrfunc2 = ( ) => {
   // Statements
};

// If function have only one statement.
var arrfunc2 = ( ) => singleStatement;
onClick, onChange,..
onClick has to call to a Javascript function. It can not call directly to a method of Component. Therefore, onClick should call to an anonymous function and inside this anonymous function, you can call the method of Component:
Arrow function with the event parameter:
// A method of Component with event parameter.
refreshCurrentTime(event) {
  var now = new Date();
  this.setState({ currentTime: now.toString() });
}

render() {
  return (
    <div>
      <h4>Current Time:</h4>
      <p>{this.state.currentTime}</p>
      <button onClick={(event) => this.refreshCurrentTime(event)}>
          Refresh Current Time
      </button>
    </div>
  );
}
For Javascript ES6, you can also call to the method of Component by this way:
.jsx
// A method of this Component.
refreshCurrentTime(event) {
  var now = new Date();
  this.setState({ currentTime: now.toString() });
}

render() {
  return (
    <div>
      <h4>Current Time:</h4>
      <p>{this.state.currentTime}</p>
      <button onClick={this.refreshCurrentTime.bind(this,event)}>
         Refresh Current Time
      </button>
    </div>
  );
}
Or:
onClick-example3.jsx
class CurrentTime extends React.Component {
  constructor(props) {
    super(props);

    var now = new Date();
    this.state = {
      currentTime: now.toString()
    };

    // (***)
    this.refreshCurrentTime = this.refreshCurrentTime.bind(this);
  }

  // A method of this Component
  refreshCurrentTime( ) {
    var now = new Date();
    this.setState({ currentTime: now.toString() });
  }
  render() {
    return (
      <div>
        <h4>Current Time:</h4>
        <p>{this.state.currentTime}</p>
        <button onClick={this.refreshCurrentTime}>
          Refresh Current Time
        </button>
      </div>
    );
  }
}

// Render
ReactDOM.render(<CurrentTime />, document.getElementById("currenttime1"));

2. Event of Child Component 

An event occurs at the child Component but you want to call to a method at parent Componen. Below is a such example.
childEvent-example.jsx
// <Child> with 1 attribute: myClickHandler
// <Child myClickHandler=.. />
class Child extends React.Component {
  render() {
    return (
      <div className="child">
        <h4>Child</h4>
        <button onClick={this.props.myClickHandler}>Click me!</button>
      </div>
    );
  }
}

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

    this.state = {
      count: 0
    };
  }

  myMethodOfParent() {
    this.setState((prevState, props) => {
      return {
        count: prevState.count + 1
      };
    });
  }

  render() {
    return (
      <div className="parent">
        <h3>(Parent) Clicked: {this.state.count} </h3>
        <Child myClickHandler={() => this.myMethodOfParent()} />
      </div>
    );
  }
}

// Render
ReactDOM.render(<Parent />, document.getElementById("placeholder1"));
childEvent-example.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS Event</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
      <style>
         .parent {
         border:1px solid #d9ebe8;
         padding: 5px;
         margin-top: 20px;
         }
         .child {
         width:150px;
         border:1px solid #8cb0aa;
         margin: 5px;
         padding: 5px;
         }
      </style>
   </head>
   <body>
      <h3>The child's event calls to parent's method</h3>

      <div id="placeholder1"></div>

      <script src="childEvent-example.jsx" type="text/babel"></script>
      
   </body>
</html>

3. A complex example

OK, and now it is a more complex example. It asks you to master a lot of knowledge in ReactJS, such as Lists, Props, State, Event.
The knowledge in ReactJS that you need to know:
complex-example.jsx
// <OrderDetail> with 4 attributes:
// productName, price, quantity, addHandler
class OrderDetail extends React.Component {
  render() {
    return (
      <div className="order-detail">
        <h4>{this.props.productName}</h4>
        <p>Price: {this.props.price} USD</p>
        <p>Quantity: {this.props.quantity}</p>
        <p>
          <button onClick={this.props.addHandler}>+</button>
        </p>
      </div>
    );
  }
}

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

    this.state = {
      amount: 0,
      details: [
        { id: 1, productName: "IPhone X", price: 900, quantity: 0 },
        { id: 2, productName: "Samsung S9", price: 800, quantity: 0 },
        { id: 3, productName: "Nokia 8", price: 650, quantity: 0 }
      ]
    };
  }

  updateOrder(index) {
    this.setState((prevState, props) => {
      console.log(this.state.details);

      var newQty = prevState.details[index].quantity + 1;
      this.state.details[index].quantity = newQty;
      this.state.amount = prevState.amount + 1 * prevState.details[index].price;
      return {
        amount: this.state.amount,
        details: this.state.details
      };
    });
  }

  render() {
    // Array of <OrderDetail ../>
    var detailTags = this.state.details.map((e, index) => (
      <OrderDetail
        key={e.id}
        addHandler={() => this.updateOrder(index)}
        productName={e.productName}
        price={e.price}
        quantity={e.quantity}
      />
    ));
    return (
      <div className="order">
        {detailTags}
        <div className="clear" />
        <p className="total">Total: <b>{this.state.amount} USD</b></p>
      </div>
    );
  }
}

// Render
ReactDOM.render(<Order />, document.getElementById("order1"));
complex-example.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS Event</title>
      <script src="https://unpkg.com/react@16.4.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@16.4.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
      <style>
         .order {
           border:1px solid #d9ebe8;
           padding: 5px;
           margin-top: 20px;
         }
         .order-detail {
            float : left;
            width:150px;
            border:1px solid #8cb0aa;
            margin: 5px;
            padding: 5px;
         }
         .clear {
           clear: both;
         }
         .total {
            margin: 5px;
         }
      </style>
   </head>
   <body>
      <h3>Complex Example (Event, List, Props, State)</h3>

      <div id="order1"></div>

      <script src="complex-example.jsx" type="text/babel"></script>

   </body>
</html>