translating between cents and dollars in html input in React

匿名 (未验证) 提交于 2019-12-03 01:18:02

问题:

I'm in a bit of a weird situation, I am dealing with currency in my we app. On the model side, I am saving currency as cents before sending to the server as I don't want to deal with decimal points on the server side. In the view however, I want the to display normal currency and not cents.

So, I have this input field where I take the data from dollars and change it to cents:

And when there's a change in the input value, I change it back to cents before sending it upstream:

handleUpdate: function(e) {    var value = e.target.value;    // changing it back from cents to dollars     value = parseFloat(value) * 100;    // save back to the parent component managing the prop   this.props.onUserUpdate(value);  } 

This puts me in kind of a deadlock, there's no way for me to enter a decimal point "." Let me demonstrate :

  1. 33 in the input box --> becomes 3300 in the parent state --> goes back as 33 in component prop - all good

  2. 33.3 in the input box --> becomes 3330 in the parent state --> goes back as 33.3 in the component prop - all good

  3. 33. in the input box --> becomes 3300 in the parent state --> goes back as 33 in the component prop - this is the problem

As you can see in case #3, when the user first enters "." this doesn't translate back to the same number with "."

Since it's a controlled input, there's basically no way of writing "."

I have tried using uncontrolled element with defaultValue, but the amount prop is not ready the time the component is rendered so it's just empty

http://jsfiddle.net/fpbhu1hs/

回答1:

Controlled inputs using derived values can be tricksy - if you need to be able to display invalid or otherwise weird input then...

  1. always hold the input's value in its component's own state

  2. derive the initial value in getInitialState()

    getInitialState: function() {   return {value: this.props.user.balance / 100} } 
  3. implement componentWillReceiveProps(nextProps) to detect when the prop's value is changing from above and re-derive the state value

    componentWillReceiveProps: function(nextProps) {   if (this.props.user.balance != nextProps.user.balance) {     this.setState({value: nextProps.user.balance / 100})   } } 

Now when the user enters "33.", you store their literal input using setState(), then call back to the parent.

handleUpdate: function(e) {   var value = e.target.value   this.setState({value: value})   this.props.onUserUpdate(parseFloat(value) * 100) } 

If the value the parent then passes back down to the child via props hasn't changed (3300 == 3300 in this case), then componentWillReceiveProps() won't do anything.

Working snippet:

} }) var Child = React.createClass({ getInitialState() { return {dollars: this.props.cents / 100} }, componentWillReceiveProps(nextProps) { if (this.props.cents != nextProps.cents) { this.setState({dollars: nextProps.cents / 100}) } }, _onChange(e) { var dollars = e.target.value this.setState({dollars}) if (!isNaN(parseFloat(dollars)) && isFinite(dollars)) { this.props.onCentsChange(parseFloat(dollars) * 100) } }, render() { return
} }) React.render(, document.querySelector('#example')) }()


回答2:

I'm using this simple solution to handle controlled inputs and decimal values.

  1. Create two props in your state, one to hold actual value and another to hold string.

    constructor(props) {     ....      this.state = {         myProperty: 1.42,         myPropertyString: '1.42'     } } 
  2. Set your input value to String one

  3. In handleUpdate method update both state variables.

    handleUpdate(e) {     this.setState({         myProperty: parseFloat(e.target.value),         myPropertyString: e.target.value     }); } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!