How to handle the onChange issue on input fields in React forms?
Hello people. Hope you all are doing well and good. In this blog I am gonna need your suggestion on how to overcome the onChange issue that I am facing while using forms in general.
Most of our project include forms which contains input fields which contains text, number, password, checkbox, select and radio-buttons. These values are generally saved in local state and are called controlled inputs.
Let us take a general scenario where we have three input fields named Total Bill(bill), discount(discount) and Payable Bill(payableBill). The first two are user inputs while the third one is auto calculated from the above two values.
Below is the simple code for the Form.js
import React, { Component } from 'react';export default class Form extends Component {
constructor(props) {
super(props);
this.state = {
bill: 0,
discount: 0,
payableBill: '',
};
}componentDidMount() {}updateState = (e) => {
e.preventDefault();
this.setState({
[e.target.name]: parseInt(e.target.value),
});
this.updatePayableBill();
};updatePayableBill = () => {
const { bill, discount } = this.state;
const amount = bill - discount;
this.setState({ payableBill: amount });
};render() {
const { bill, discount, payableBill } = this.state;
return (
<div className="container">
<form>
<div className="d-flex flex-column">
<label htmlFor="bill">Total Bill:</label> <br />
<input
type="number" name="bill"
onChange={(e) => this.updateState(e)}
value={bill ? bill : ''}
/>
</div>
<div className="d-flex flex-column">
<label htmlFor="discount">Discount:</label> <br />
<input
type="number" name="discount"
onChange={(e) => this.updateState(e)}
value={discount ? discount : ''}
/>
</div>
<div className="d-flex flex-column">
<label htmlFor="payableBill">Payable Bill:</label><br/>
<input
type="number" name="payableBill"
disabled value={payableBill ? payableBill : ''}
/>
</div>
</form>
</div>
);
}
}
Whenever there is a change in the input fields the update state function is called. Inside the function we will search for the input name and its value. And the use setState to update its value in state and call the updatePayableBill function. Inside this payabaleBill function we calculate the payable bill based on the values of the actual bill and the discount amounts. Payable bill will be the difference in the amounts of total bill (bill) and the discount amount(discount). Finally we set the difference amount to its value in the state object.
The main problem here is the uupdatePayableBill function is getting called even before the setState({}) action is completed in the updateState function. Because of this calculation error is happening in the payableAmount value.
Let me explain you with an example. If I enter 250 in the bill input, while entering the updatePayableBill function, the value of bill is getting only 25 from the state object. This is occurring because of the delay in setState function.
I have handled it using the following procedure:
updateState = (e) => {
e.preventDefault();
const { bill, discount } = this.state;
var amount;
if(e.target.name === 'bill'){
amount = parseInt(e.target.value) - discount;
}else{
amount = bill - parseInt(e.target.value)
}
this.setState({
[e.target.name]: parseInt(e.target.value),
payableBill: amount
});
};
Here I have used two conditions to calculate the payableAmount value based on the type of input field we enter. This will solve my issue for now. What if I have many input fields on which I have to auto-calculate a value.
It would be a great help if you suggest any methods (other than the above I mentioned) to overcome this issue. Thank you very much for taking out your time and reading this blog.