在React中的html输入中转换美分和美元

Mic*_*ael 7 javascript reactjs

我有点奇怪的情况,我在我的应用程序中处理货币.在模型方面,我在发送到服务器之前将货币保存为美分,因为我不想在服务器端处理小数点.然而,在视图中,我希望显示正常货币而不是美分.

所以,我有这个输入字段,我从美元中获取数据并将其更改为美分:

<input name="balance" type="number" step="0.01" min="0" placeholder="Balance in cents" onChange={this.handleUpdate} value={this.props.user.balance / 100)} />
Run Code Online (Sandbox Code Playgroud)

当输入值发生变化时,我会在将其发送到上游之前将其更改为美分:

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);

}
Run Code Online (Sandbox Code Playgroud)

这让我陷入僵局,我无法输入小数点"." 让我来证明:

  1. 33在输入框中 - >变为3300父状态 - > 33在组件prop中返回 - 一切都很好

  2. 33.3在输入框中 - >变为3330父状态 - > 33.3在组件prop中返回 - 全部好

  3. 33.在输入框中 - >变为3300父状态 - >返回33组件prop中 - 这就是问题所在

正如您在第3种情况中所看到的,当用户首次输入"."时 这不会转换回与"."相同的数字.

由于它是一个受控制的输入,基本上没有办法写"."

我已经尝试过使用不受控制的元素defaultValue,但是数量prop没有准备好组件被渲染的时间所以它只是空的

http://jsfiddle.net/fpbhu1hs/

Jon*_*nan 11

使用派生值的受控输入可能很棘手 - 如果您需要能够显示无效或其他奇怪的输入,那么......

  1. 始终将输入保存value在其组件中state

    <input value={this.state.value} onChange={this.handleUpdate} // rest as above...
    
    Run Code Online (Sandbox Code Playgroud)
  2. 得出最初valuegetInitialState()

    getInitialState: function() {
      return {value: this.props.user.balance / 100}
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 实现componentWillReceiveProps(nextProps)以检测prop的值何时从上方变化并重新导出状态值

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

现在,当用户输入"33."时,您使用存储他们的文字输入setState(),然后回叫父母.

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

如果父级然后通过道具传回给孩子的值没有改变(3300 == 3300在这种情况下),那么componentWillReceiveProps()就不会做任何事情.

工作片段:

<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
<div id="example"></div>
<script type="text/jsx;harmony=true">void function() { 'use strict';

var Parent = React.createClass({
  getInitialState() {
    return {cents: 3300}
  },
  
  _changeValue() {
    this.setState({cents: Math.round(Math.random() * 2000 + Math.random() * 2000)})
  },

  _onCentsChange(cents) {
    this.setState({cents})
  },

  render() {
    return <div>
      <p><strong>Cents:</strong> {this.state.cents.toFixed(0)} <input type="button" onClick={this._changeValue} value="Change"/></p>
      <Child cents={this.state.cents} onCentsChange={this._onCentsChange}/>
    </div>
  }
})

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 <div>
      <input type="number" step="0.01" min="0" value={this.state.dollars} onChange={this._onChange}/>
    </div>
  }
})

React.render(<Parent/>, document.querySelector('#example'))

}()</script>
Run Code Online (Sandbox Code Playgroud)