Reputation: 141
I'm using React to try to build a calculator which performs a number of tax calculations when the user enters in their day rate via a form. This has required me to use setState to create quite a lot of variables within my 'handleSubmit' function, the formulation of the values for most of which incorporate the values of previously created variables. After a bit of trial and error, it became apparent that I couldn't do this without nesting a new setState component inside the previous component used to create the variable that I'm looking to call upon. I've shared my handleSubmit function below:
handleSubmit = (event) => {
event.preventDefault()
this.setState({
rate: event.target.value
}, () => {
this.setState({
totalFees: this.state.rate * 220
})
if (this.state.totalFees <= 8632) {
this.setState({
incomeTax: 0,
nationalInsurance: 0
});
} else if (this.state.totalFees <= 12500) {
this.setState({
incomeTax: 0,
nationalInsurance: ((this.state.totalFees - 8632) * .12)
});
} else if (this.state.totalFees <= 50000) {
this.setState({
incomeTax: ((this.state.totalFees - 12500) * .2),
nationalInsurance: ((this.state.totalFees - 8632) * .12)
});
} else if (this.state.totalFees <= 150000) {
this.setState({
incomeTax: (7500 + ((this.state.totalFees - 50000) * .4)),
nationalInsurance: (4964.16 + ((this.state.totalFees - 50000) * .02))
});
} else {
this.setState({
totalFees: this.state.rate * 220,
incomeTax: (47500 + ((this.state.totalFees - 150000) * .45)),
nationalInsurance: (4964.16 + ((this.state.totalFees - 50000) * .02))
}, () => {
this.setState({
combined: this.state.incomeTax + this.state.nationalInsurance,
insideAnnual: this.state.totalFees - (this.state.incomeTax + this.state.nationalInsurance)
}, () => {
this.setState({
insideMonthly: Math.round((this.state.insideAnnual / 12) * 100) / 100
})
})
})
}
})
The main issue that I'm having is that, while a variable seems to be able to call on the value of another variable when it is nested directly within it, this doesn't appear to be the case when the variable is further away. For example, my application is currently returning NaN for the variable 'insideAnnual', which calculates three variable values - 'totalFees', 'incomeTax' and 'nationalInsurance'.
Having logged the values from the same nested area that 'insideAnnual' is contained, the values for 'incomeTax' and 'nationalInsurance' were correct when returned to the console, but NaN was returned for 'totalFees' which is near the top of the function and appears to be the problem. I'm wondering what the workaround is, because when I attempt to promote the insideAnnual variable outside of its nested component, it fails to incorporate the incomeTax and nationalInsurance values.
Also, this function is already quite lengthy yet still incomplete, as I haven't created the nested components for each if statement yet. If anybody has any tips for how I could make it more succinct, that would also be much appreciated.
Apologies for the longwinded explanation!
Upvotes: 0
Views: 44
Reputation: 1827
Firstly, you might get weird results, since event.target.value
is a string, so it's best to convert it into a number. parseInt(event.target.value, 10)
.
Secondly, you don't need to nest the setStates, you can create temporary variables within the function, and at the end update the state value. E.g:
const rate = parseInt(event.target.value, 10);
const totalFees = rate * 220;
let incomeTax = 0;
let nationalInsurance = 0;
if (totalFees <= 12500) {
// incomeTax stays the same, no need to update
nationalInsurance = ((totalFees - 8632) * .12)
} else if (...) {
// other calculations
}
// After all that logic is done, you set the state:
this.setState(
{
rate: rate,
incomeTax: incomeTax,
nationalInsurance: nationalInsurance
// combined,
// insideAnnual
// insideMonthly
}
);
You can further improve this, by creating separate functions for calculating nationalInsurance
, incomeTax
, combined
, insideAnnual
and insideMonthly
.
UPDATE:
For example to calculate the incomeTax
, you can create another function such as:
const calculateIncomeTax = (totalFees) => {
switch(true) {
case totalFees <= 8632:
return 0;
case totalFees <= 12500:
return 0;
case totalFees <= 50000:
return ((totalFees - 12500) * .2);
case totalFees <= 150000:
return (7500 + ((totalFees - 50000) * .4));
default:
return (47500 + ((totalFees - 150000) * .45))
}
};
And just call it, within your handleSubmit
function:
const incomeTax = calculateIncomeTax(totalFees);
Upvotes: 1
Reputation: 13077
You should build up a local copy of the data you want to store and then only call setState once with all your changes in it.
Upvotes: 1