React.js, improve generating object from form inputs

Viewed 111

In vanilla JS I could just use formData for this, and make an Object.fromEntries() from it.
In React I wasn't sure how to do this right, so here's what I came up with after some googling around:

class App extends Component{
  constructor(props){
    super(props);

    this.autoData = {
      title:'',
      description:'',
      year:'',
      color:'',
      status:'',
      price:''
    }
  }

  handleAutoData = e => {
    if (e.target.id in this.autoData) {
      this.autoData[e.target.id] = e.target.value
    }
  }

  handleAutoForm = e => {
    e.preventDefault()   
    if (Object.keys(this.autoData).every(k => this.autoData[k])) {
      this.props.addAuto(this.autoData)
    }
  }

  render(){
    ...

    return (
      <div className="App">
        <form className="form" onSubmit={this.handleAutoForm}>
          <input type="text" className="form_text" placeholder="Name" id="title" onChange={this.handleAutoData} />
          <input type="text" className="form_text" placeholder="Year" id="year" onChange={this.handleAutoData} />
          <input type="text" className="form_text" placeholder="Price" id="price" onChange={this.handleAutoData} />
          <input type="text" className="form_text" placeholder="Details" id="description" onChange={this.handleAutoData} />
          <button type="submit"> Send &gt; </button>
        </form>
      </div>
    )
  }
}

This does the job and handleAutoForm pushes the object into Redux store. However:

  • Is there a better alternative for onChange event? I know it's the go-to way of handling form inputs, but right now it's spamming/overwriting my values on every keystroke. I'd only like to push a value once I stop typing/field loses focus. Out of alternatives, I saw articles of onFocusOut, but it's not supported or has issues.
  • Right now I'm mutating the component's state directly. Not sure if it's critical, since I'll be pushing the state to Redux anyway. I wanted a local object inside handleAutoData, just so I could write the values into it, but every time an onChange is called, a new object is made and it overwrites the previous values. Problem is, I can't use setState because of e.target's nature - it keeps complaining about missing brackets on render, because of all the dots (when I do something like this.setState({autoData[e.target.id]:e.target.value}) ). And if I assign it to a temporary variable (like let autoKey = e.target.id), setState pushes the autoKey as key, instead of e.target.id. What could be done with this?
1 Answers

Usual way is to use name or id along with onChange event.

state = {
  title:'',
  description:'',
  year:'',
  color:'',
  status:'',
  price:''
 }

 handleChange = (e) => {
   this.setState({
     [e.target.name]:e.target.value
 });

  handleSubmit = (e)=>{
    e.preventDefault();
    //Push state to redux,make API 
    call etc
  }
Related