我刚刚创建了我的第一个React应用https://split-calc.herokuapp.com/
如果我先填写顶部表格,然后单击“添加人”,则一切正常。但是,如果我在填写顶部表格之前单击“添加人员”,则在填写顶部表格后,不会更新人员编号。即使我将每个值都设置为链接到状态,为什么会发生这种情况?
function Header() {
return (
<header>Split Bill Calculator</header>
)
}
function AddPerson(props) {
return (
<div className='button'>
<button className='addPerson' onClick={props.onClicked}>Add Person</button>
</div>
);
}
function PersonList(props) {
return (
<div>
{props.persons.map((person, index) => (
<span key={index}>{person}</span>
))}
</div>
);
};
class Details extends React.Component {
constructor(props) {
super(props);
this.state = {
meal_total: 0,
shared_items: 0,
tax: 0,
tip: 0,
persons: [],
counter: 1,
};
this.handleClick = this.handleClick.bind(this)
this.handleMealChange = this.handleMealChange.bind(this)
this.handleSharedItemsChange = this.handleSharedItemsChange.bind(this)
this.handleTaxChange = this.handleTaxChange.bind(this)
this.handleTipChange = this.handleTipChange.bind(this)
}
handleMealChange = event => {
this.setState({
meal_total: event.target.value,
});
};
handleSharedItemsChange = event => {
this.setState({
shared_items: event.target.value,
});
};
handleTaxChange = event => {
this.setState({
tax: event.target.value,
});
};
handleTipChange = event => {
this.setState({
tip: event.target.value,
});
};
handleClick = () => {
let counter = this.state.counter + 1
let addPerson = this.state.persons.concat(this.renderPerson())
this.setState({
persons: addPerson,
counter: counter,
});
}
renderPerson = () => {
return (
<Person
person_tax = {this.state.tax}
person_tip = {this.state.tip}
shared_items = {this.state.shared_items}
counter = {this.state.counter}
/>
)
}
renderAddPerson = () => {
return (
<AddPerson
onClicked= {() => this.handleClick()}
/>
);
}
render() {
let grand_total = parseFloat(this.state.meal_total) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tax)/100)) + ((parseFloat(this.state.meal_total)) * (parseFloat(this.state.tip)/100));
return (
<div className='details'>
<div className='order-total'>
<form>
<label htmlFor='meal'>Meal subtotal: ($)</label><br></br>
<input name='meal' placeholder={this.state.meal_total} onChange={this.handleMealChange}></input><br></br>
<label htmlFor='meal'>Shared items: ($)</label><br></br>
<input name='meal' placeholder={this.state.shared_items} onChange={this.handleSharedItemsChange}></input><br></br>
<label htmlFor='tax'>Tax: (%)</label><br></br>
<input name='tax' placeholder={this.state.tax} onChange={this.handleTaxChange}></input><br></br>
<label htmlFor='tip'>Tip: (%)</label><br></br>
<input name='tip' placeholder={this.state.tip} onChange={this.handleTipChange}></input><br></br>
<label htmlFor='total'>Grand Total: ($)</label><br></br>
<input name='total' value={grand_total.toFixed(2)} readOnly></input><br></br>
</form>
</div>
<PersonList persons={this.state.persons} />
{this.renderAddPerson()}
</div>
);
}
}
class Person extends React.Component {
constructor(props) {
super(props);
this.state = {
person_tax: props.person_tax,
person_tip: props.person_tip,
person_meal_subtotal: 0,
shared_items: props.shared_items,
}
}
handlePersonSubtotal = event => {
this.setState({
person_meal_subtotal: event.target.value
});
};
render() {
let person_total = parseFloat(this.state.person_meal_subtotal) + parseFloat(this.props.shared_items) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tax)/100)) + ((parseFloat(this.state.person_meal_subtotal)) * (parseFloat(this.state.person_tip)/100));
let shared_items = this.state.shared_items / this.props.counter;
return (
<div className='person'>
<div className='total-details'>
<h3>Person {this.props.counter} </h3>
<form>
<label htmlFor='person-meal'>Personal Subtotal: $ </label>
<input name='person-meal' value={this.state.person_meal_subtotal} onChange={this.handlePersonSubtotal}></input>
</form>
</div>
<div className='breakdown'>
<h3>Should Pay</h3>
<div className='person-details'>
<p>Shared: ${(parseFloat(shared_items)).toFixed(2)}</p><br></br>
<p>Tax: ${((parseFloat(this.state.person_tax)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p><br></br>
<p>Tip: ${((parseFloat(this.state.person_tip)/100) * parseFloat(this.state.person_meal_subtotal)).toFixed(2)}</p><br></br>
<p>Total: ${person_total.toFixed(2)}</p>
</div>
</div>
</div>
)
}
}
class Calculator extends React.Component {
render() {
return (
<div>
<Header />
<Details/>
</div>
)
}
}
ReactDOM.render(<Calculator />, document.getElementById('root'));
答案 0 :(得分:0)
第一个建议是,如果表单未填写,则不允许用户添加人员。
基于对上面代码的分析,您没有将状态与对象的人数数组链接,也没有更新值。每次更改仅更新有关状态的全局数据。
this.state = {
meal_total: 0, /*updated*/
shared_items: 0, /*updated*/
tax: 0, /*updated*/
tip: 0, /*updated*/
persons: [], /*not updated on each action update, its only getting re-render or getting the state during new person add action*/
counter: 1, /*updated*/
};
您需要更新state.persons:[]每个动作到唯一的person数组
handleTaxChange = event => {
this.setState({
tax: event.target.value,
persons: <-- update the number of persons selected array with tax -->
});
};
调用渲染人员列表的代码,每次渲染时似乎都有旧值->
<PersonList persons={this.state.persons} />
您需要访问并更新个人税。
快乐编码!