问题
Consider the following input element in a React component:
<input onChange={() => console.log('onChange')} ... />
While testing the React component, I'm emulating user changing the input value:
input.value = newValue;
TestUtils.Simulate.change(input);
This causes 'onChange'
to be logged, as expected.
However, when the 'change'
event is dispatched directly (I'm using jsdom):
input.value = newValue;
input.dispatchEvent(new Event('change'));
the onChange
handler is not called.
Why?
My motivation to use dispatchEvent
rather than TestUtils.Simulate
is because TestUtils.Simulate
doesn't support event bubbling and my component's behavior relies on that. I wonder whether there is a way to test events without TestUtils.Simulate
?
回答1:
React uses its own events system with SyntheticEvents
(prevents browser incompatabilities and gives react more control of events).
Using TestUtils
correctly creates such a event which will trigger your onChange
listener.
The dispatchEvent
function on the other hand will create a "native" browser event. But the event handler you have is managed by react and therefore only reacts (badumts) to reacts SyntheticEvents
.
You can read up on react events here: https://facebook.github.io/react/docs/events.html
回答2:
One way to do it without ReactTestUtils.Simulate
:
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://unpkg.com/react-trigger-change/dist/react-trigger-change.js';
document.head.appendChild(script);
input.value = value;
reactTriggerChange(input);
Look at the source of react-trigger-change to just cherry-pick what's needed. Example snippet:
if (nodeName === 'select' ||
(nodeName === 'input' && type === 'file')) {
// IE9-IE11, non-IE
// Dispatch change.
event = document.createEvent('HTMLEvents');
event.initEvent('change', true, false);
node.dispatchEvent(event);
}
- https://github.com/vitalyq/react-trigger-change
- https://github.com/facebook/react/issues/3249#issuecomment-292919084
来源:https://stackoverflow.com/questions/39065010/why-react-event-handler-is-not-called-on-dispatchevent