react: Trigger simulated input value change for React 16 (after react-dom 15.6.0 updated)?
I’m trying to trigger the input/change event on a React form outside react using pure JS or jQuery. With react-dom 15.6.0 you were able to use simulated flag on the event object for the event to pass through
var element = document.getElementById("inputToTriggerByJS");
var ev = new Event('input', { bubbles: true});
ev.simulated = true;
element.value = "Something new";
element.defaultValue = "Something new";
element.dispatchEvent(ev);
Note I cannot use React even though the form trying to trigger on is based on React, have to pure JS or jQuery to trigger the input value change event.
So the original suggestion from this comment used to work: https://github.com/cypress-io/cypress/issues/536#issuecomment-308739206
But after React 16 release this is not triggering the input and change event as expected.
What are the internal changes as to how it handles changes to input data in React 16?
Believe there is a point here which would give the hint: reactjs.org/blog/2017/09/26/react-v16.0.html#breaking-changes Any idea what it could be?
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 20
- Comments: 39 (4 by maintainers)
After some research of react source code, I got a hack method for react 16:
NOTICE: JUST A HACK
Can you just call
setState
on the component instance that renders the input to have it take a different value?Can you expand on why you need this? It is not exactly clear what your constraints are.
More general (or maybe less hacky) way is described here: https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js#46012210
PS. I’m not the author.
this worked for me. changing a select menu on a compiled react page, and making sure the appropriate change events fire.
This is very needed for Selenium tests automation - it’s hard to set value for input type color
For me the event type
input
did not work on some applications as @whosesmile suggested so I found out thatchange
works better:With text input (text area included) the event “input” works, but not “change”. With select tags the event “change” works but not “input”. Thanks again.
Good job figuring out this hack!
Thx all!
This is what I ended up using in typescript:
You have no idea how long I have been searching for this. THANK YOU.
@gaearon I have the most basic possible use case for this, I’m making a typical input with clear button component, to be a drop-in replacement for an
<input>
. Like the<input>
it wraps, it communicates with the outside world viavalue
andonChange
. Clicking the clear button needs to somehow callonChange
with a valid event whereevent.currentTarget.value
is''
. Feels like this ought to be easy and not require any hacks.Calling
setState
on whatever would break encapsulation since this component is supposed to be as dumb as<input>
.@whosesmile what is _valueTracker? cant find it in any docs
It seems like this workaround broke in 16.13 for us. Did anyone else run into issues with upgrading?
Browser extensions expect to be able to influence form values.
See this for a solution: https://github.com/facebook/react/issues/10135#issuecomment-314441175
It is to interact with a React based website’s form from a proprietary web browser which has to use the external form. The browser has limited access to external scripts. It is just one of those legacy systems that has to interact with a modern SPA web page to trigger a form submission. The legacy system which supports JS and jQuery may be deprecated. But really just need to figure out how to trigger this input value change as it worked in the past. I can at most put inline JS code or possibly a external JS URL to refer to external library if I have use ReactTestUtils as a simulate method. Was hoping to not be in this situation, but trying to resolve with what is possible in the interim.
Generic method for changing input in React (Shamelessly taken from here)
Answers in this thread weren’t working for me when editing a TextArea, but this does!
Also to @gaearon some of us are building browser extensions, which can come with a plethora of constraints
I’ve found the
_valueTracker.setValue
“trick” to be perfectly working with only:Just needed a little cleanup and this worked for me.
@whosesmile thanks for the hack! My use case is I have a bunch of bookmark scripts that do things such as auto-login, or auto-fill forms with various test data. When you have a constant stream of new development servers, autofill usually doesn’t work. I’ve had to update these scripts several times with new React versions.
You can put the reference to your component onto the input, for example.
Yep I could, but how can do that using the console or outside the React scope? for example in this codepen: https://codepen.io/gkitarp/pen/pdNRKP
I don’t have direct access to the React component, only the global scope of console is used. So in the example the //Outside the React scope is what I have access to and can edit.
Here’s a sandbox demonstrating the
ClearableInput
I want (currently using the hack outlined above): https://codesandbox.io/s/brave-ganguly-cp6m7?file=/src/ClearableInput.jsA good example of where this might be necessary is when interacting with https://github.com/escaladesports/react-hubspot-form. The component interface does not provide any way to initialize values for a form, the component does not store input values in “state” so
ref.setState
isn’t an option, and theonReady
callback only returns a jquery form object that points to an iframe(?!).Anyway, the only way (I’ve found) to initialize this form is to do so by manipulating the inputs on the DOM and manually triggering react to pick up the changes.
FWIW: I would agree that this is a problem with the react-hubspot-form interface (https://github.com/escaladesports/react-hubspot-form/issues/13), and not necessarily with React itself (I’ll leave that to you all). I just thought I’d provide some context.
Thanks for the response! So the full isolated simple example is as follows: Using React 15.6.1 input: https://codepen.io/gkitarp/pen/LObxVd Using React 16.0.0 input: https://codepen.io/gkitarp/pen/pdNRKP As per the example, when you click on the submit button on React 16 the value has not been changed, but on React 15.6.1 it works due to the use of simulated dispatch event.
Basically I have to use pure JS or jQuery (without React access) to enter some values in some input fields within a form rendered by React 16. Earlier the form and input fields was rendered with React 15.6.x but after the form/site updated to React 16 the pure JS way of simulating input value change stopped working.
So looking to quickly know how to trigger or simulate input value update so it follows the right dispatch event sequence or method in React 16.
I’m unsure if I can use ReactTestUtils as a simulate method just by injecting the react and react-dom 16.0.0 standard scripts as I don’t have access to the original form’s React implementation. I prefer to trigger this with HTML dom and JS. But guess that is unreliable so wondering if using ReactTestUtils as a standalone to trigger input change will work?