Seun Lanlege
Seun Lanlege

Reputation: 1346

How to handle multiple controlled inputs with react es6?

Here's my fiddle

https://codepen.io/seunlanlege/pen/XjvgPJ?editors=0011

I have two inputs and I'm trying to use one method to handle the onChange event for any input field.

I've torn the internet apart looking for a solution but came up with nothing.

I'm using es6 please how do I go about this?

class Form extends React.Component {
  `constructor(props) {
    super(props);
    this.state = {text:{
      e:'hi',
      c:''
    }};
    this.handleSubmit = this.handleSubmit.bind(this);
  }`

  `handleChange(event,property) {
    const text = this.state.text;
      text[property] = event.target.value;
      this.setState({text});
  }`

  `handleSubmit(event) {
    alert('Text field value is: ' + this.state.text.e);
  }`

  `render() {
    return (
      <div>
        <div>{this.state.text.e}</div>
        <input type="text"
          placeholder="Hello!"
          value={this.state.text.e}
          onChange={this.handleChange.bind(this)} />
        <input type="text"
          placeholder="Hello!"
          value={this.state.text.c}
          onChange={this.handleChange.bind(this)} />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}`

ReactDOM.render(
  `<Form />`,
  document.getElementById('root')
);

Upvotes: 2

Views: 1824

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 281626

You have not passed the propert to the handeChange function. pass it like this.handleChange.bind(this, 'e') and also the order of receiving props is wrong, property will be the first argument and then the event and not the reverse.

Code:

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {text:{
      e:'hi',
      c:''
    }};
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(property, event) {
    console.log(event.target.value);
    const text = {...this.state.text};
      text[property] = event.target.value;
      this.setState({ text }); //or you can use the shorthand here. ES6 is awesome <3
  }

  handleSubmit(event) {
    alert('Text field value is: ' + this.state.text.e);
  }

  render() {
    return (
      <div>
        <div>{this.state.text.e}</div>
        <div>{this.state.text.c}</div>
        <input type="text"
          placeholder="Hello!"
          value={this.state.text.e}
          onChange={this.handleChange.bind(this, 'e')} />
        <input type="text"
          placeholder="Hello!"
          value={this.state.text.c}
          onChange={this.handleChange.bind(this, 'c')} />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('root')
);

CodePen

Upvotes: 3

Fabian Schultz
Fabian Schultz

Reputation: 18546

One way to do this would be to give each of your inputs a name attribute and set the state based on that:

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = { text: {
      e: 'hi',
      c: ''
    } };
    this.onChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(e) {
    var oldState = this.state.text;
    var newState = { [e.target.name]: e.target.value };
    
    // I have to assign/join because you've put the text state in a parent object.
    this.setState({ text: Object.assign(oldState, newState) });
  }

  handleSubmit(event) {
    alert('Text field value is: ' + this.state.text.e);
  }

  render() {
    console.log(this.state);
    return (
      <div>
        <div>{this.state.text.e}</div>
        <input type="text"
          placeholder="Hello!"
          name="e"
          value={this.state.text.e}
          onChange={this.onChange} />
        <input type="text"
          placeholder="Hello!"
          name="c"
          value={this.state.text.c}
          onChange={this.onChange} />
        <button onClick={this.handleSubmit}>
          Submit
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('View')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react-dom.min.js"></script>
<div id="View"></div>

Also, there are so-called two-way binding helpers. As I understand they still show mixins in React's documentation, so you are probably better off with third party libraries like react-link-state:

this.state = {
  username: '',
  password: '',
  toggle: false
};

<input type="text" valueLink={linkState(this, 'username')} />
<input type="password" valueLink={linkState(this, 'password')} />
<input type="checkbox" checkedLink={linkState(this, 'toggle')} />

Upvotes: 2

Related Questions