Is there an easier way to connect an input field to a state property in React than onChange?

So take a look at this code below for our example, a simple two-way data binding in an input field connecting a field to a property inputValue

.

But tell me you have a more complex page with 30 or more entries. Do you intend to write 30+ onChange

handler in the class, all with different names corresponding to the input type onNameChange

, onEmailChange

, onPhoneChange

etc.? Isn't there a neater, more implicit way to bind input data than what I have below?

React.createClass({
  getInitialState() {
    inputValue: ''
  },
  render() {
    return (
      <input
        type='text'
        value={this.state.inputValue}
        onChange={this.onChange} />
    );
  },
  onChange(e) {
    this.setState({ inputValue: e.target.value });
  }
});

      

Edit: I suppose I could do this and not write handlers in the class:

<input onChange={ e => this.setState({firstName: e.target.value}) } />

      

Is it kosher?

+3


source to share


2 answers


The React docs has your solution:

https://facebook.github.io/react/docs/forms.html#handling-multiple-inputs



    class NameForm extends React.Component {
      constructor(props) {
        super(props);
        this.state = {value: ''};

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }

   handleInputChange(event) {
    const target = event.target;    
    this.setState({
      [target.name]: target.value
    });
  }

      handleSubmit(event) {
        alert('A name was submitted: ' + this.state.value);
        event.preventDefault();
      }

      render() {
        return (
          <form onSubmit={this.handleSubmit}>
            <label>
              Name:
              <input name="name" type="text" value={this.state.name} onChange={this.handleInputChange} />
            </label>
            <label>
              Email:
              <input name="email" type="text" value={this.state.email} onChange={this.handleInputChange} />
            </label>
                  <label>
              Pet:
              <input name="country" type="text" value={this.state.country} onChange={this.handleInputChange} />
            </label>
            <input type="submit" value="Submit" />
          </form>
        );
      }
    }

      

+2


source


An easier way would be to have one handler onChange

and pass an ID to it, and store the value with that ID. Your solution will look like

React.createClass({
  getInitialState() {

  },
  onChange(e, type) {
     this.setState({[type]: e.target.value})

  },
  render() {
    return (
      <input
        type='text'
        value={(this.state.inputValue)? this.state.inputValue: ''}
        onChange={this.onChange.bind(this, 'inputValue')} />
      <input
        type='text'
        value={(this.state.emailValue)? this.state.emailValue: ''}
        onChange={this.onChange.bind(this, 'emailValue')} />
    );
  },
  onChange(e) {
    this.setState({ inputValue: e.target.value });
  }
});

      

The value is set using ternary operator expression

, because initially the state is undefined and, therefore, we get awarning that input is trying to change the uncontrolled input to controlled.

Another way is to have an inline handler like

onChange={ e => this.setState({inputValue: e.target.value}) }

      



but let's say you have 30 inputs that you need to define their initial state and let it set its value as above, only the difference - this value assigned to it should be with an expression as shown in the first example

Another way to assign value to input like @MayankShukla suggestessted would be

value = {this.state.inputValue || ''}

      

with getInitialState looks like

getInitialState() {
    return {}
},

      

+1


source







All Articles