What is the best way to trigger change or input event in react js

reactjs

Solution

For React ≥ 15.6.1

To trigger a React’s `change` event handler registered on an `input` element, you should set the `value` property on the element using the native setter before dispatching the event (if you set the `value` directly it will not work because it will use React’s overridden setter):

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
  window.HTMLInputElement.prototype,
  'value').set;
nativeInputValueSetter.call(input, newValue);
const event = new Event('input', { bubbles: true });
input.dispatchEvent(event);

CodePen example

Same solution for the `textarea` element by substituting `HTMLTextAreaElement`.

All credits go to this Cypress contributor and his solution.

For React ≤ 15.6.0

To trigger a React’s `change` event handler registered on an `input` element, you should set the `value` property on the element and set the `simulated` property on the event (React specific) before dispatching the event:

input.value = newValue;
const event = new Event('input', { bubbles: true });
event.simulated = true;
input.dispatchEvent(event);

CodePen example

To understand why `simulated` is needed, I found this comment very helpful:

The input logic in React now dedupe's change events so they don't fire more than once per value. It listens for both browser `onChange`/`onInput` events as well as `set`s on the DOM node `value` prop (when you update the value via javascript). This has the side effect of meaning that if you update the input's value manually `input.value = 'foo'` then dispatch a `ChangeEvent` with `{ target: input }` React will register both the `set` and the event, see it's value is still `'foo', consider it a duplicate event and swallow it.

This works fine in normal cases because a "real" browser initiated event doesn't trigger `set`s on the `element.value`. You can bail out of this logic secretly by tagging the event you trigger with a `simulated` flag and react will always fire the event. https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128

Problem

We use Backbone + ReactJS bundle to build a client-side app. Heavily relying on notorious `valueLink` we propagate values directly to the model via own wrapper that supports ReactJS interface for two way binding. Now we faced the problem: We have `jquery.mask.js` plugin which formats input value programmatically thus it doesn't fire React events. All this leads to situation when model receives unformatted values from user input and misses formatted ones from plugin. It seems that React has plenty of event handling strategies depending on browser. Is there any common way to trigger change event for particular DOM element so that React will hear it?

Original source