javascriptreactjsformsonsubmit

React.js: submit form programmatically does not trigger onSubmit event


I want to submit a React form after a click on a link.

To do so I need to submit the form programmatically if the link is clicked.

my problem is : onSubmit handler is not being fired after the form submit .

Here is a code snipped that I made for this purpose:

var MyForm = React.createClass({
  handleSubmit: function(e){
    console.log('Form submited');
     e.preventDefault();
  },
  submitForm : function(e){
    this.refs.formToSubmit.submit();
  },
  render: function() {
    return (
    <form ref="formToSubmit" onSubmit={this.handleSubmit}>
    <input name='myInput'/>
    <a onClick={this.submitForm}>Validate</a>
    </form>);
  }
});

ReactDOM.render(
  <MyForm name="World" />,
  document.getElementById('container')
);

The handleSubmit is not invoked and the default behavior is executed (the form being submitted). Is this a ReactJs bug or a normal behavior? Is there a way to get the onSubmit handler invoked ?


Solution

  • Update 2021

    The solution from the accepted answer didn't work for me so I decided to update this topic.

    React 16 (and older)

    In the original answer, the second parameter of the Event constructor is missing. Without {cancelable: true} parameter, the preventDefault() method cannot be run.

    <div>
        <form onSubmit={e => e.preventDefault()} ref={ref => this.form = ref}>
            <input name="tmp" />
        </form>
    
        <button onClick={e => this.form.dispatchEvent(
            new Event("submit", { cancelable: true })
        )}>
            Submit form
        </button>
    </div>
    

    React 17 (and probably newer versions in the future)

    In the current version of React (17), there has been a quire big change in event delegation (details here). Thus, the solution above needs a small improvement to work with this version of the library. This change is the bubbles: true parameter. Working code would look like this:

    <div>
        <form onSubmit={e => e.preventDefault()} ref={ref => this.form = ref}>
            <input name="tmp" />
        </form>
    
        <button onClick={e => this.form.dispatchEvent(
            new Event("submit", { cancelable: true, bubbles: true })
        )}>
            Submit form
        </button>
    </div>