Search code examples
javascriptreactjsecmascript-6async-awaites6-promise

Async method to return true or false on React component


I'm working on a React component that handles a form submit.

<form
    name="theForm"
    ref={(el) => { this.theForm = el }}
    onSubmit={this.handleSubmit}
    noValidate
>

On the submit event handler I perform validation, using HTML5 form checkvalidity() calling another function, validateForm();

handleSubmit(e) {
    e.preventDefault();
    if (this.validateForm()) {
        //Call the api to post data
    }
}

If the validity on validateForm is false, I populate a list on state called dirtyFormInputs that is passed to the form's child components.

Due to setState async behaviour, I changed my code to handle the updates to dirtyFormInputs list with async/await as follows:

async validateForm() {
    const formLength = this.theForm.length;

    if (this.theForm.checkValidity() === false) {
        this.setState({ dirtyFormInputs: [] });  
        for(let input of this.theForm){
            input.nodeName.toLowerCase() !== 'button' 
                && await this.validateInput(input);
        }
        return false;
    }
    return true;
}

But since I changed the validateInput method to properly update dirtyFormInputs, the return false statement on validateForm() is not effective anymore and my form is submitted even when failing on valitidy check.

validateInput(input) {
    if (!input.validity.valid) {
        return new Promise((resolve) => {
            this.setState({
                dirtyFormInputs: [...this.state.dirtyFormInputs, input.name]
            }, resolve)
        });
    }
}

Solution

  • validateForm returns a promise since it's declared async.

    You need to wait for the promise to resolve:

    handleSubmit(e) {
      e.preventDefault();
      this.validateForm().then(result => { // or use `async` + `await`
        if (!result) return; 
        //Call the api to post data
      });
    }