1

When I click submit on the button, only 1 value is submitted to the object instead of both. I have worked out that the state is updated correctly until the submit button is pressed and only 1 value is submitted into the obj.

I have used the functions as below:

  onChange = (event) => {
    this.setState({ term: {term1: event.target.value }});
  }

  onChange2 = (event) => {
    this.setState({ term: {term2: event.target.value }});
  }

  onSubmit = (event) => {
    event.preventDefault();
    let obj = {
        result1: this.state.term.term1,
        result2: this.state.term.term2,     
    };
    {console.log('obj', obj)}
    this.setState({
        term: {
            term1: '',
            term2: ''
        },
        items: [...this.state.items, obj]
    });
  }

I have used the render as below:

render() {
    return (
      <div>
        <form onSubmit={this.onSubmit}>
          <input value={this.state.term.term1} onChange={this.onChange} />
          <input value={this.state.term.term2} onChange={this.onChange2} />
          <button>Submit</button>
        </form>
        <List items={this.state.items} />
      </div>
    );
  }

My state structure is as follows:

this.state = {
  term: {
    term1: '',
    term2: ''
  },
  items: []
};

Any help would be great! Thank you!

R1992
  • 23
  • 4

4 Answers4

0

It's because you're mutating the term state. You need to update the state like:

onChange = (event) => {
  this.setState({ term: {...this.state.term, term1: event.target.value }});
}

Do the similar approach with onChange2. And then you'll get the merged term: term1 and term2.

You may even use updater callback like this:

onChange = (event) => {
  this.setState((prevState) => ({
     term: {
       ...prevState.term,
       term1: event.target.value
     }
  }))
 }

You may even just define single handler for both changes as commented by Henok:

onChange = (event, termNum) => {
  this.setState((prevState) => ({
     term: {
       ...prevState.term,
       [termNum]: event.target.value
     }
  }))
 }

And pass the termNum with responding term1, or term2 in your onChange:

onChange={this.onChange(term1)}
// there are sorts of methods to pass the parameter.

You may check my another post for further details about using parameters.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
  • Thank you! This worked like a treat! For my understanding, why do you need to add the ...this.state.term? – R1992 Oct 02 '18 at 17:06
  • 1
    Without the spread operator (...) you are simply replacing the term object each time onChange is called so `term: {term1: 'something'}` becomes `term: {term2: 'something else'}` – adam.k Oct 02 '18 at 17:09
  • And instead of using two methods , onChange & onChange 2 you can use computed property. onChange = (event, termNum) => { this.setState({ term: {...this.state.term, [termNum]: event.target.value }}); } – Henok Tesfaye Oct 02 '18 at 17:19
0

Try below change

 onChange = (event) => {
      this.setState(prevState => ({
         term: {
            ...prevState.term,
           term1: event.target.value
         }
      }))
 }

 onChange2 = (event) => {
     this.setState(prevState => ({
         term: {
            ...prevState.term,
           term2: event.target.value
         }
     }))
 }
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
0

I believe your state is overwriting itself each time your onChange functions are called. If you use the spread operator you'll keep your current values of state without over writing it.

onChange2 = (event) => {
    this.setState({ 
      term: {
        ...this.state.term,
        term2: event.target.value 
      }
    })
  }

Do the same for the other onChange even you have as well.

adam.k
  • 622
  • 3
  • 15
-1

Try like this

onSubmit = (value1, value2) = ev => {
   ev.preventDefault();
   console.log(value1,value2)
 }

and call like this

 <form onSubmit={this.onSubmit(this.state.term.term1,this.state.term.term2)}>