简体   繁体   中英

React Native - Trying to update an amount but it's not updating properly when passing down from parent to child

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM