Reactコンポーネント内の次の入力要素を検討してください。
<input onChange={() => console.log('onChange')} ... />
Reactコンポーネントをテストしている間、ユーザーが入力値を変更することをエミュレートしています:
input.value = newValue;
TestUtils.Simulate.change(input);
これにより、期待どおり'onChange'
がログに記録されます。
ただし、'change'
イベントが直接ディスパッチされる場合(私はjsdomを使用しています):
input.value = newValue;
input.dispatchEvent(new Event('change'));
onChange
ハンドラーは呼び出されません。
どうして?
TestUtils.Simulate
ではなくdispatchEvent
を使用する動機は、TestUtils.Simulate
がイベントバブリングをサポートしておらず、コンポーネントの動作がそれに依存しているためです。 TestUtils.Simulate
なしでイベントをテストする方法があるかしら?
ReactはSyntheticEvents
を使用して独自のイベントシステムを使用します(ブラウザーの非互換性を防ぎ、reactでより多くのイベントを制御できます)。
TestUtils
を正しく使用すると、onChange
リスナーをトリガーするイベントが正しく作成されます。
一方、dispatchEvent
関数は、「ネイティブ」ブラウザイベントを作成します。しかし、あなたが持っているイベントハンドラーはreactによって管理されているので、反応するだけで(badumts)SyntheticEvents
に反応します。
あなたはここで反応イベントについて読むことができます: https://facebook.github.io/react/docs/events.html
ReactTestUtils.Simulate
なしでそれを行う1つの方法:
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);
react-trigger-changeのソース を見て、必要なものを簡単に選択してください。スニペットの例:
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);
}