score:1

'...' spread operator produces a shallow copy of an object

handlechange(evt, field) { 
let form = {...this.state.form};  //object spread notation
form[field] = evt.value;
console.log('change triggered'); 
this.setstate({ form: form }); 

}

score:1

when it comes to forms with react, there are two approaches.

1) uncontrolled components, which basically making use of refs and getting values from the dom (please check the official documentation for more details https://reactjs.org/docs/uncontrolled-components.html) or

2) controlled components making use of states and getting/handling values from react states (please check the official documentation for more details https://reactjs.org/docs/forms.html#controlled-components)

with controlled components => react, state is the single source of truth (as official document suggests), that means, you need to provide methods to handle state changes as user provides the input

with uncontrolled components => instead of updating state on every single change, you can get values inside of onsubmit method and handle them before submit. since you won't need to update the state, you won't need additional functions to handle state changes.

for you seeking of better way to handling things and avoid mutations, it actually depends on your use case, but official documentation suggests that

in most cases, we recommend using controlled components to implement forms. in a controlled component, form data is handled by a react component

when it comes to mutating object, indeed mutations is not good, but there are ways to avoid mutations during state changes. as @mhkit already suggested, you can use spread operator to create a new object (shallow copy, that means it only copies the values) or you could use object.assign() method.

let's say you have the following state

state = {
 form: {
  email: '',
  name: '',
  lastname: '',
  }
}

when you user provides the email, you basically need to update the email field, in that case in your handlechangeemail() method, what you can do is the following

this.handlechangeemail = (value) => { 
this.setstate(({form}) => {
   return {
     form: {
      ...form,
     email: value 
    }
})
}

so with this method, what i basically do is, 1) i utilize functional setstate and extracted the current value of form via es6 object destructuring, then i say that, okay my new form object inside of the state, will have all the existing field that former form has, but, the email field will have a new value based on the new input user provided.

by this way, instead of mutating form object, we created a shallow copy of it with some values are exactly the same, but some values are updated. thus we prevent the mutation

score:2

if you don't want to update each character change you can use onblur event.

 onblur={event => { this.handlechange(event, 'name'); }}

so that on leaving the field only you can update the state.


Related Query

More Query from same tag