Component response and invalid input

I have the following react component:

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.net/2hauj2qg/

The problem is if I want to enter a number like "4.7". When the user enters "4." it becomes "4" due to the fact that it converts to a float at the back. But this interrupts what the user was entering. What is the recommended way to solve this problem?

+3


source to share


4 answers


As mentioned above, this is because you are using parseFloat

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

      

Instead, you can only allow digits and decimal numbers. It stays stored as a string and never changes their input, but they fail to type characters 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 enter a leading dollar sign and no more than two decimal places, and if the first character (after $) is decimal, prefix it with 0.

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

      

+4


source


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

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

      



http://jsfiddle.net/2hauj2qg/1/

0


source


If it makes no sense to do something with the number until after they are entered, and you follow the standard way of creating an event to transmit changed data, you can execute 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 much sense in this isolated example, but if you are assuming that someone is using MyComponent and that they are giving them an onChange callback, then this works well. You get the benefits of inline input control, but still return (via callback) the number as an actual float.

0


source


How do I write a small component that will process string values ​​and only pass legal float values ​​to 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)
      }
    }
  };

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

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

      

0


source







All Articles