Reputation: 173
I'm building a web app that calculates BMR by asking the user for age, weight, gender, feet, inches. After the user submits the form, there should be an alert box with the state of all objects. The only problem is, BMR is the only one that stays at 0; it doesn't update until I click submit again. I am working with two Classes: Macros(main) and Form. My code is below
class Macros extends React.Component{
constructor(props){
super(props);
this.state = {
age: '',
weight: '',
male: true,
feet: '',
inches: '',
BMR: 0,
};
this.handleAgeChange = this.handleAgeChange.bind(this);
this.handleWeightChange = this.handleWeightChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleGenderChange = this.handleGenderChange.bind(this);
this.handleFeetChange = this.handleFeetChange.bind(this);
this.handleInchChange = this.handleInchChange.bind(this);
this.calculateBMR = this.calculateBMR.bind(this);
}
handleAgeChange(event) {
this.setState({age: event.target.value});
}
handleWeightChange(event) {
this.setState({weight: event.target.value});
}
handleSubmit(event) {
this.calculateBMR();
event.preventDefault();
alert('Age: ' + this.state.age + ' Weight: ' + this.state.weight + ' Male: ' + this.state.male
+ ' Feet: ' + this.state.feet + ' Inches: ' + this.state.inches + ' BMR: ' + this.state.BMR)
}
handleGenderChange(event) {
this.setState({male: !this.state.male});
}
handleFeetChange(event) {
this.setState({feet: event.target.value});
}
handleInchChange(event) {
this.setState({inches: event.target.value});
}
calculateBMR() {
let calBMR = 0;
if(this.state.male){
calBMR = ((10 * ((this.state.weight) / 2.20462)) +
(6.25 * ((this.state.feet * 30.48) + (this.state.inches * 2.54))) -
(5 * this.state.age)) + 5;
}
else {
calBMR = ((10 * ((this.state.weight) / 2.20462)) +
(6.25 * ((this.state.feet * 30.48) + (this.state.inches * 2.54))) -
(5 * this.state.age)) - 161;
}
this.setState({BMR: calBMR});
}
render(){
const title = 'Macro Apps';
const subtitle = 'Calculate Your Macro-Nutrient Intake for Flexible Dieting';
return (
<div>
<Header title={title} subtitle={subtitle} />
<Form onAgeChange={this.handleAgeChange} onWeightChange={this.handleWeightChange}
onGenderChange={this.handleGenderChange} onFeetChange={this.handleFeetChange}
onInchChange={this.handleInchChange} onSubmit={this.handleSubmit}
/>
</div>
);
}
}
ReactDOM.render(<Macros />, document.getElementById('root'));
Form Class
import React from 'react';
export class Form extends React.Component{
render(){
return (
<div>
<form onSubmit={this.props.onSubmit}>
Age:
<input type="text" onChange={this.props.onAgeChange}/><br />
Weight:
<input type="text" onChange={this.props.onWeightChange} /><br />
<label>
<input
type="radio"
name="gender"
checked="checked"
onChange={this.props.onGenderChange}
/>
Male
</label>
<label>
<input
type="radio"
name="gender"
onChange={this.props.onGenderChange}
/>
Female<br/>
</label>
<input type="text" onChange={this.props.onFeetChange}/>ft
<input type="text" onChange={this.props.onInchChange}/>in<br/>
<input type="submit" value="Submit" />
</form>
</div>
)
}
}
Upvotes: 1
Views: 132
Reputation: 21
you can change like below or try to use Mobx
`class Macros extends React.Component{
constructor(props){
super(props);
this.state = {
age: '',
weight: '',
male: true,
feet: '',
inches: '',
BMR: 0,
};
this.handleAgeChange = this.handleAgeChange.bind(this);
this.handleWeightChange = this.handleWeightChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleGenderChange = this.handleGenderChange.bind(this);
this.handleFeetChange = this.handleFeetChange.bind(this);
this.handleInchChange = this.handleInchChange.bind(this);
this.calculateBMR = this.calculateBMR.bind(this);
}
handleAgeChange(event) {
this.setState({age: event.target.value},this.calculateBMR);
}
handleWeightChange(event) {
this.setState({weight: event.target.value},this.calculateBMR);
}
handleSubmit(event) {
event.preventDefault();
alert('Age: ' + this.state.age + ' Weight: ' + this.state.weight + ' Male: ' + this.state.male
+ ' Feet: ' + this.state.feet + ' Inches: ' + this.state.inches + ' BMR: ' + this.state.BMR)
}
handleGenderChange(event) {
this.setState({male: !this.state.male},this.calculateBMR);
}
handleFeetChange(event) {
this.setState({feet: event.target.value},this.calculateBMR);
}
handleInchChange(event) {
this.setState({inches: event.target.value},this.calculateBMR);
}
calculateBMR() {
let calBMR = 0;
if(this.state.male){
calBMR = ((10 * ((this.state.weight) / 2.20462)) +
(6.25 * ((this.state.feet * 30.48) + (this.state.inches * 2.54))) -
(5 * this.state.age)) + 5;
}
else {
calBMR = ((10 * ((this.state.weight) / 2.20462)) +
(6.25 * ((this.state.feet * 30.48) + (this.state.inches * 2.54))) -
(5 * this.state.age)) - 161;
}
this.setState({BMR: calBMR});
}
render(){
const title = 'Macro Apps';
const subtitle = 'Calculate Your Macro-Nutrient Intake for Flexible Dieting';
return (
<div>
<Header title={title} subtitle={subtitle} />
<Form onAgeChange={this.handleAgeChange} onWeightChange={this.handleWeightChange}
onGenderChange={this.handleGenderChange} onFeetChange={this.handleFeetChange}
onInchChange={this.handleInchChange} onSubmit={this.handleSubmit}
/>
</div>
);
}
}
ReactDOM.render(<Macros />, document.getElementById('root'));
`
Upvotes: 0
Reputation: 1774
In ReactJS setting state is asynchronous. You can simply pass a callback
to setState
method like this:
setState({ "something": "needs to change" }, () => { /* will be invoked when the state changes. */ })
So this lines of code:
handleSubmit(event) {
this.calculateBMR();
...
}
calculateBMR() {
...
this.setState({BMR: calBMR});
}
Could be look like this:
handleSubmit(event) {
this.calculateBMR(() => {
alert('Age: ' + this.state.age + ' Weight: ' + this.state.weight + ' Male: ' + this.state.male +
' Feet: ' + this.state.feet + ' Inches: ' + this.state.inches + ' BMR: ' + this.state.BMR)
});
}
calculateBMR(callback) {
this.setState({ BMR: calBMR }, callback);
}
Upvotes: 2