0

I was learning Forms in React and I came across the below code where a single setState method is used for multiple inputs to update the value provided by the user. Can anyone explain what spread operator doing here, what does it hold inside the setState method?

  class FormContainer extends Component {

  constructor () {

  this.state = {
      formControls: {
          email: {
            value: ''
          },
          name: {
            value: ''
          },
          password: {
            value: ''
          }
      }
  }

}

 changeHandler = event => {

  const name = event.target.name;
  const value = event.target.value;

  this.setState({
    formControls: {
        ...this.state.formControls,
        [name]: {
        ...this.state.formControls[name],
        value
      }
    }
  });
}


  render() {
     return (
      <form>

          <input type="email" 
                 name="email" 
                 value={this.state.formControls.email.value} 
                 onChange={this.changeHandler} 
          />

          <input type="text" 
                 name="name" 
                 value={this.state.formControls.name.value} 
                 onChange={this.changeHandler} 
          />

          <input type="password" 
                 name="password" 
                 value={this.state.formControls.password.value} 
                 onChange={this.changeHandler} 
          />

       </form>      
     );
   }

}

 export default FormContainer;**

Source: https://medium.com/@agoiabeladeyemi/the-complete-guide-to-forms-in-react-d2ba93f32825

Nag
  • 806
  • 1
  • 13
  • 28
  • it's needed if you want to preserve current values of other fields/inputs ... used to create new state object - requred for detecting updates, decision if rerendering required – xadm Mar 10 '20 at 12:56

2 Answers2

0

It creates a new object with the a key formControls and the value for that key is composed of all properties that are in this.state.formControls (basically a shallow copy of the old state). The [name]: {...this.state.formControls[name], value} part then overrides the key that equals name with a new object that is composed of the current properties from this.state.formControls[name] and the key value overridden with what is in value:

this.setState({
    formControls: {
        ...this.state.formControls, // shallow copy of current state
        [name]: { // overrides key that equals what is in name
            ...this.state.formControls[name], // shallow copy of current states formControls[name]
            value // overrides value
        }
    }
});

Or simply said it sets a copy of the current state, but with the value in state.formControls[name] changed with what is in value, as the new state.

trixn
  • 15,761
  • 2
  • 38
  • 55
  • I understood the first ...this.state.formControls, which is more like the previous state, after that can we not do simply like [name]: value? do we need ...this.state.formControls[name] ? – Nag Mar 11 '20 at 04:28
  • something like this - this.setState(prevState => ({ ...prevState, name: evt.target.value, })) – Nag Mar 11 '20 at 04:29
0

setState in React should not mutate state. Instead with help of the spread operator a new object is being created containing the old values and the new [name] property.

zszep
  • 4,450
  • 4
  • 38
  • 58
  • can you tell me what exactly happening here - [name]: { ...this.state.formControls[name], value } – Nag Mar 11 '20 at 11:03
  • In javascript you have two options naming properties in objects: 1. object notation 2. bracket notation. [name] is the second one. Name is the name attribute of the html element. – zszep Mar 12 '20 at 12:29