score:2

Accepted answer

From your OP, you seem to have some confusion on what really happens under the hood.

I for one, would prefer to handle errors as required fields, purely with the html5 required attribute.

It will not submit the form, until all field validations are handled.

So if you need a required text field, just use:

<input type="text" required />

This will automatically indicate that this input field needs a value (handling updating the state with the changed value is covered in the code sample below).

For the rest it seems to be all about control, do you want the parent component to handle the errors in your child control, or should the child control handle those errors? You seem to want to have both, I really wouldn't bother with sending the full state to the parent, all the parent should really care about, is what I send :)

Handling your internal state of the child component is another thing, but you are not really showing how you set your form variables at the moment. In my case, I use controlled inputs, meaning, the value they have is never undefined, and I have an onChange eventhandler attached to them to update the child components state, which changes the input element in the following state

<input type="text" required name="firstName" value={ this.state.firstName } onChange={ this.updateField } />

Where updateField is defined in the following way

updateField( e ) {
  // name is the name given to the input field, in the sample 'firstName'
  const { name, value } = e.target;
  // and I update the state as
  this.setState({ [name]: value });
}

After the this.setState has completed, a new render will start, and the firstName will get the new value that was just set to it.

At this time, when all required fields are filled out, the handleSubmit function will be called when clicking the submit button, and I can send the data I actually want to send to my parent form, the state has the latest information, and there is no need to handle any error handling, as the browser would have taken care of that already.

const { Component } = React;

class SomeForm extends Component {
  constructor() {
    super();
    this.handleSubmit = this.handleSubmit.bind( this );
    this.updateField = this.updateField.bind( this );
    this.state = {
      firstName: '', lastName: ''
    };
  }
  handleSubmit(e) {
    const { onSubmit } = this.props;
    const { firstName, lastName } = this.state;
    e.preventDefault();
    onSubmit({ firstName, lastName });
  }
  updateField( e ) {
    const { target } = e;
    const { name } = target;
    this.setState({
      [name]: target.value
    });
  }
  render() {
    const { firstName, lastName } = this.state;
    return (
      <form onSubmit={ this.handleSubmit }>
        <div>
          <span>First name:</span>
          <span>
            <input 
              type="text" 
              name="firstName" 
              value={ firstName } 
              required
              onChange={ this.updateField } />
          </span>
        </div>
        <div>
          <span>Last name:</span>
          <span>
            <input 
              type="text" 
              name="lastName" 
              value={ lastName } 
              required
              onChange={ this.updateField } />
          </span>
        </div>
        <div>
          <button>Submit</button>
        </div>
      </form>
    );
  }
}

class InputDataHandler extends Component {
  constructor() {
    super();
    this.onSubmit = this.onSubmit.bind( this );
  }
  onSubmit( inputData ) {
    console.log( inputData );
  }
  render() {
    return (
      <div>
        <SomeForm onSubmit={this.onSubmit} />
      </div>  
    );
  }
}

const container = document.getElementById('container');
ReactDOM.render( <InputDataHandler />, container );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>

Clearly, you shouldn't only consider client side validation, but handle the input server side as well to ensure that your client side validation didn't get bypassed, but that's in your case a side note.

score:-1

I hope it will be useful for You: https://reactjs.org/docs/error-boundaries.html#how-about-event-handlers.

How about to wrap onFormSubmit calling in try/catch?

 errorHandling = (error) => {
    this.setState({ error });
    // !this.state.origin ? this.setState({ originError: true }) :   this.setState({ originError: false });
    // !this.state.destination ? this.setState({ destinationError: true }) :    this.setState({ destinationError: false });
    // !this.state.date ? this.setState({ dateError: true }) :     this.setState({ dateError: false });
    // !this.state.time ? this.setState({ timeError: true }) :     this.setState({ timeError: false });
 }
 handleSubmit = (e) => {
  e.preventDefault();

  try {
    const { onFormSubmit } = this.props;
    onFormSubmit(this.state);
  } catch (error) {
    this.errorHandling(error);
  }
}

Also recommend to read about setState async


Related Query

More Query from same tag