React Cookbook
上QQ阅读APP看书,第一时间看更新

How to do it...

This recipe is straightforward, and the goal is to bind a method using the class constructor and using arrow functions:

  1. Let's create a new component called Calculator. We will create a basic calculator with two inputs and one button. The skeleton of our component is as follows:
  import React, { Component } from 'react';
import './Calculator.css';

class Calculator extends Component {
constructor() {
super();

this.state = {
number1: 0,
number2: 0,
result: 0
};
}

render() {
return (
<div className="Calculator">
<input
name="number1"
type="text"
value={this.state.number1}
/>
{' + '}
<input
name="number2"
type="text"
value={this.state.number2}
/>

<p><button>=</button></p>
<p className="result">{this.state.result}</p>
</div>
);
}
}

export default Calculator;
File: src/components/Calculator/Calculator.js
  1. Now we are going to add two new methods, one to handle the inputs (onChange event) and one to manage the result button (onClick). We can use the same handleOnChange method for both inputs. Since we have the names of the fields (which are the same as the state) we can dynamically update each state, and in the handleResult method, we just sum both numbers:
    handleOnChange(e) {
const { target: { value, name } } = e;

this.setState({
[name]: Number(value)
});
}

handleResult(e) {
this.setState({
result: this.state.number1 + this.state.number2
});
}
  1. Now in our render method, we need to add the events to the inputs and the button:
    render() {
return (
<div className="Calculator">
<input
onChange={this.handleOnChange}
name="number1"
type="text"
value={this.state.number1}
/>
{' + '}
<input
onChange={this.handleOnChange}
name="number2"
type="text"
value={this.state.number2}
/>
<p>
<button onClick={this.handleResult}>=</button>
</p>
<p className="result">{this.state.result}</p>
</div>
);
}

  1. Our CSS code for this is as follows:
  .Calculator {
margin: 0 auto;
padding: 50px;
}

.Calculator input {
border: 1px solid #eee;
font-size: 16px;
text-align: center;
height: 50px;
width: 100px;
}

.Calculator button {
background: #0072ff;
border: none;
color: #fff;
font-size: 16px;
height: 54px;
width: 150px;
}

.Calculator .result {
border: 10px solid red;
background: #eee;
margin: 0 auto;
font-size: 24px;
line-height: 100px;
height: 100px;
width: 100px;
}
File: src/components/Calculator/Calculator.css
  1. If you run the application right now, you will see that if you try to write something in the inputs or you click on the button, you will get an error such as this:
  1. The reason is that we need to bind those methods to the class to have access to it. Let's bind our methods first using our constructor:
    constructor() {
super();

this.state = {
number1: 0,
number2: 0,
result: 0
};

// Binding methods
this.handleOnChange = this.handleOnChange.bind(this);
this.handleResult = this.handleResult.bind(this);
}
  1. Using the constructor to bind the methods is good if you want to list all of them on the top of the component. If you look at the Calculator component, it should look like this:
  1. Now let's use arrow functions to automatically bind our methods instead of doing it on the constructor. For this you need to remove your bindings methods in the constructor and change the handleOnChange and handleResult methods to arrow functions:
    constructor() {
super();

this.state = {
number1: 0,
number2: 0,
result: 0
};
}

// Changing this method to be an arrow function
handleOnChange = e => {
const { target: { value, name } } = e;

this.setState({
[name]: Number(value)
});
}

// Changing this method to be an arrow function
handleResult = e => {
this.setState({
result: this.state.number1 + this.state.number2
});
}
  1. You will get the same result. I prefer arrow functions to bind methods because you use less code and you don't need to add the methods to the constructor manually.