Events in React are handled by react-dom, through different plugins. Input events are managed with the SimpleEventPlugin (see https://github.com/facebook/react/blob/master/packages/react-dom/src/events/SimpleEventPlugin.js)
This plugin gets an event and redispatches it without interfering too much. So you can dispatch it as a native event, and it'll be triggered as a SyntheticEvent without much changes.
Change event is handled by the ChangeEventPlugin (see https://github.com/facebook/react/blob/master/packages/react-dom/src/events/ChangeEventPlugin.js). This plugins has this purpose:
This plugin creates an onChange
event that normalizes change events
across form elements. This event fires at a time when it's possible to
change the element's value without seeing a flicker.
The plugin triggers change event but not exactly as the native change event. The native change event on text input element for example is triggered only on blur. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
For some elements, including , the change event
doesn't fire until the control loses focus.
But with React, it's triggered differently, on every change of value. To do this, it is handled by the plugin which has these restrictions:
The event will be triggered only on these input types:
color: true,
date: true,
datetime: true,
'datetime-local': true,
email: true,
month: true,
number: true,
password: true,
range: true,
search: true,
tel: true,
text: true,
time: true,
url: true,
week: true
So on hidden inputs, react stops the dispatch.
Another restriction is that the event will be dispatched only if the value of the input actually changes. See
if (updateValueIfChanged(targetNode)) {
return targetInst;
}
So even on a supported input, your dispatch won't go through the plugin. You can see it in this snippet, by manipulating a method that is used to get the value of the input you can manage to dispatch the event.
class Hello extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
//_valueTracker.getValue is used for comparing the values of the input. If you write fake value in the input it'll dispatch, anything else won't
document.getElementsByTagName('INPUT')[0]._valueTracker.getValue = () => {
return 'fake value'
}
}
render() {
const handleClick = () => {
if (this.myRef) {
this.myRef.current.dispatchEvent(new Event("change", {
bubbles: true
}));
}
};
return <div > < input type = "text"
ref = {
this.myRef
}
onChange = {
(e) => {
console.log("React:onChange");
}
}
/><button type="button" onClick={handleClick}>Hit it</button > < /div>
}
}
ReactDOM.render( <
Hello name = "World" / > ,
document.getElementById('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>
So for a hidden input, there's no way to make it work (note that it is in line with the standard). For a text (or other supported inputs), you can but you need to more or less hack the method comparing the value before the event with the value after the event.