I'm trying to make a Tip Calculator app with React Native where the user inputs a total amount on the text field, and the tip amount will be shown to the user as shown below.
As you can see, the amount is off and the reason is probably how I'm taking in my text input:
<Text>Total Amount: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={this.handleTotalAmount}
onSubmitEditing={this.handleTotalAmount}
/>
However, I did find a workaround where if I use onSubmitEditing
as well, the field will properly update when I hit return. This doesn't really sit well with me because I feel like I'm hacking it together without really knowing how it's working and that I also feel like there's a better solution to passing down an updating value to another class.
Here are other bits of my code if it is helpful in showing how I structured my app. I have a class TotalAmount
that has a TextInput
that will take in a totalAmount
, and I want to pass that totalAmount
into my class TipAmount15
to calculate the tip amounts. I was able to have everything in a single class, but because I want to add more tip amounts, I wanted to separate the classes. Please let me know if there's a better way of updating or if there's a better TextInput
property to use than onChangeText
or onSubmitEditing
! Help is much appreciated.
class TotalAmount extends Component {
constructor(props) {
super(props);
this.state = {
totalAmount: ''
}
}
handleTotalAmount = (totalAmountInput) => {
this.setState({
totalAmount: totalAmountInput
})
}
render() {
return (
<View>
<View style={styles.totalAmountContainer}>
<Text>Total Amount: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={this.handleTotalAmount}
onSubmitEditing={this.handleTotalAmount}
/>
</View>
<TipAmount15
percent={15}
totalAmount={this.state.totalAmount}/>
</View>
)
}
}
class TipAmount15 extends Component {
constructor(props) {
super(props);
this.state = {
percent: '',
totalAmount: '',
tipAmount15:'',
postTipAmount15:''
}
}
componentWillReceiveProps(props) {
var percent = this.props.percent;
var totalAmountInput = this.props.totalAmount;
this.setState({totalAmount: totalAmountInput})
//Calculate Tip Percentages
this.setState({tipAmount15: parseFloat(totalAmountInput*(percent/100)).toFixed(2)})
this.setState({postTipAmount15: parseFloat(totalAmountInput * (1+(percent/100))).toFixed(2)})
}
render() {
return (
<View style={styles.tipCalculatorContainer}>
<Text>{this.props.percent}%</Text>
<Text>Tip Amount: {this.state.tipAmount15}</Text>
<Text>Total Amount: {this.state.postTipAmount15}</Text>
</View>
)
}
}
Couple thoughts:
1) You should be able to refactor TipAmount
to something a bit simpler eg (note need to type convert at the end in this example)
const TipAmount15 = ({ percent, totalAmount }) => {
const tipAmount = parseFloat(totalAmount * (percent/100)).toFixed(2)
return (
<View style={styles.tipCalculatorContainer}>
<Text>{this.props.percent}%</Text>
<Text>Tip Amount: {tipAmount}</Text>
<Text>Total Amount: {Number(totalAmount) + Number(tipAmount)}</Text>
</View>
)
}
because all we are doing is a couple calculations for presentation to User. Everything we display can be easily converted from the given props so there is no real need for this component to hold its own state.
2) Why does the TextInput
in the TotalAmount
component need to handle both onChange
and submit
if they are both just calling the same handler? I do not think you need both in this case.
The issue was I was incorrectly using componentWillReceiveProps
.
componentWillReceiveProps(newProps) {
if(newProps.totalAmount != this.props.totalAmount){
var percent = this.props.percent;
var totalAmountInput = newProps.totalAmount;
this.setState({totalAmount: totalAmountInput});
this.setState({tipAmount15: parseFloat(totalAmountInput*(percent/100)).toFixed(2)})
this.setState({postTipAmount15: parseFloat(totalAmountInput * (1+(percent/100))).toFixed(2)})
}
}
When checking if there has been a change, it now properly updates with the text field onChangeText
and solved my issue.
However, even though this did solve my original issue, I'm still unaware if there is a better way of passing the information through.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.