12

Speechless fiddle with reproducing of situation

The key code is:

class Form extends React.Component {
 handleSubmit(evt) {
 evt.preventDefault()
 var data = {}
 for (var i = 0; i < this.form.elements.length; i++) {
 var elt = this.form.elements[i]
 if (elt.name) {
 data[elt.name] = elt.value
 }
 }
 this.props.onSubmit(data)
 return false
 }
 submit() {
 if (this.form.checkValidity())
 this.form.dispatchEvent(new Event('submit'))
 }
 render() {
 return (
 <form onSubmit={this.handleSubmit.bind(this)} ref={r => this.form = r}>
 {this.props.children}
 </form>
 )
 }
}

After this.form.dispatchEvent() the evt.preventDefault() in handleSubmit() doesn't work in Firefox

If you open fiddle in Chrome (e.g.) and enter data into fields, you will see it in console - the prevention of dispatched event will work perfectly.

In Firefox preventing doesn't work - after logging data the page immediately reloads (see "APP CONSTRUCTOR" in console).

So, the question is obvious: how to avoid this bug?

asked Mar 31, 2018 at 12:50
4
  • Did you try event.stopPropagation() ? Commented Mar 31, 2018 at 12:55
  • @Meir yep, still no changes. Updated Fiddle Commented Mar 31, 2018 at 13:01
  • Looks like evt is actually a Proxy and not an Event? (not sure if related) Commented Mar 31, 2018 at 13:04
  • @PaulS. yes, but evt.nativeEvent is an native event, and the evt.nativeEvent.preventDefault() gives no changes Commented Mar 31, 2018 at 13:06

1 Answer 1

39

First, this is not a react-specific question.

how to avoid this bug?

It seems that { cancelable: true } flag prevents Firefox from reloading the page in this case.

this.form.dispatchEvent(new Event('submit', { cancelable: true }))

Here's a full and simple example:

<!Doctype html>
<html>
 <head>
 <script type="text/javascript">
 document.addEventListener("DOMContentLoaded", function(event) {
 const form = document.querySelector('#testform');
 const button = form.querySelector('button');
 form.onsubmit = function (e) {
 e.preventDefault();
 e.stopPropagation();
 console.log('submitting the form ...');
 
 // return true;
 return false;
 };
 // https://developer.mozilla.org/en-US/docs/Web/API/Event/Event
 // cancelable: (optional) a Boolean indicating whether the event can be cancelled. The default is false.
 const submitEvent = new Event('submit', { 
 cancelable: true
 });
 // https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted
 // The isTrusted read-only property of the Event interface is a boolean that is true when the event was generated by a user action, and false when the event was created or modified by a script or dispatched via dispatchEvent.
 console.log('is event trusted', submitEvent.isTrusted) // false
 console.log('is event cancelable', submitEvent.cancelable) // true
 button.onclick = function () {
 console.log('button clicked');
 const cancelled = form.dispatchEvent(submitEvent);
 // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent
 // The return value is false if event is cancelable and at least one of the event handlers which handled this event called Event.preventDefault(). Otherwise it returns true.
 console.log('is cancelled', !cancelled);
 }
 });
 </script>
 </head>
 <body>
 <form id="testform">
 <input type="hidden" name="a" value="b">
 <p>Hit the button a couple times, the page should not refresh.</p>
 <button type="button">click</button>
 </form>
 </body>
</html>

Why this happens:

https://www.chromestatus.com/features/5718803933560832 According to the UI Events specification un-trusted events (i.e. those created by JavaScript) should not invoke the default action.

If you change the cancelable flag to false and try the test in Chrome, it would still work, because (as far as I understand) it is still an untrusted event (created not by direct user interaction with UI) and Chrome does not run default handlers for untrusted events.

But, I'm not sure why Firefox still runs default handlers for untrusted events.

answered Mar 31, 2018 at 21:50
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer. Seems like it fixes the problem)
Thanx, you are the GOAT!

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.