最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Component and Invalid Input - Stack Overflow

programmeradmin4浏览0评论

I have the following react ponent:

var App = React.createClass({
    getInitialState: function() {
        return {value: 4.5}
    },
    change: function(event) {
        this.setState({value: parseFloat(event.target.value)});
    },
    render: function() {
        return <input type="number" value={this.state.value} onChange={this.change}/>;
    }
});

React.render(<App/>, document.body);

You can see it here: /

The problem is that if I want to type in a number like: "4.7". When the user enters, "4.", it bees "4", due to being converted to a float in back. But this interrupts what the user was typing. What's the remended way of solving this problem?

I have the following react ponent:

var App = React.createClass({
    getInitialState: function() {
        return {value: 4.5}
    },
    change: function(event) {
        this.setState({value: parseFloat(event.target.value)});
    },
    render: function() {
        return <input type="number" value={this.state.value} onChange={this.change}/>;
    }
});

React.render(<App/>, document.body);

You can see it here: http://jsfiddle/2hauj2qg/

The problem is that if I want to type in a number like: "4.7". When the user enters, "4.", it bees "4", due to being converted to a float in back. But this interrupts what the user was typing. What's the remended way of solving this problem?

Share Improve this question asked Dec 23, 2014 at 3:01 Winston EwertWinston Ewert 45.1k10 gold badges69 silver badges86 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 5

As imjared mentioned, it's because you're using parseFloat

this.setState({value: parseFloat(event.target.value)});

Instead, you may wish to only allow digits and the decimal. It stays stored as a string and never changes their input, but they're prevented from typing things like letters and spaces.

var nonNumericRegex = /[^0-9.]+/g;

this.setState({value: event.target.value.replace(nonNumericRegex, "")});

To allow negative numbers you need to do this:

this.setState({
    value: event.target.value
        .replace(nonNumericRegex, "")
        .replace(/^(-.*?)-/g, "$1")
});

To enforce a leading dollar sign and no more than two decimals, and if the first character (after the $) is the decimal, prefix it with 0.

this.setState({
    value: "$" + event.target.value
        .replace(nonNumericRegex, "")
        .replace(/(\.\d\d)\d+/g, "$1")
        .replace(/^\./g, "0.")
})

Remove the parseFloat and your string won't be cast to a number?

    change: function(event) {
        this.setState({value: event.target.value});
    }

http://jsfiddle/2hauj2qg/1/

If it doesn't make sense to do anything with the number until they're done typing and you follow the standard way of raising an event to signal changed data, you can acplish it with the following:

var MyComponent = React.createClass({
    getInitialState: function() {
        return {value: 4.5};
    },
    change: function(event) {
        this.setState({value: event.target.value});
    },
    blur: function(event) {
        this.props.onChange({value: parseFloat(event.target.value)});
    },
    render: function() {
        return <input type="number" value={this.state.value} onBlur={this.blur} onChange={this.change}/>;
    }
});

React.render(<MyComponent/>, document.body);

It doesn't make too much sense in this isolated example, but if you assume someone is using MyComponent and that they give it an onChange callback, then this works nicely. You get the benefits of a native input control but still return (through the callback) the number as an actual float.

What about writing a small ponent that will handle string values and pass only legal float values to the listeners ?

class NumberInput extends React.Component<{ onChange: (n: number) => void, value: number }, { value: number }> {

  constructor(props: { onChange: ((n: number) => void); value: number }, context: any) {
    super(props, context);
    this.state = {
      value: props.value || 0
    };
  }

  handleInputChange = (e) => {
    const value = e.target.value;
    this.setState({
      value: value
    });
    if (this.props.onChange) {
      const floatValue = parseFloat(value);
      if (!isNaN(floatValue)) {
        this.props.onChange(floatValue)
      }
    }
  };

  ponentWillReceiveProps(newProps) {
    this.setState({
      value: newProps.value
    })
  }

  render() {
    return (
      <Input step="0.1" value={this.state.value} onChange={this.handleInputChange} type="number"/>
    )
  }
}
发布评论

评论列表(0)

  1. 暂无评论