Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the 'change' event in jQuery fire onChange in ReactJS?

Tags:

I am writing tests for ReactJS components in karma + PhatomJS. I am rendering the component and using jQuery as a shortcut to target dom elements and simulate user actions. Clicking, text input, etc works fine. However, the selection in a select doesn't seem to execute the component's onChange event. Here's the code:

import React from 'react'
import ReactDOM from 'react-dom'
import $ from 'jquery'

class SelectComponent extends React.Component {
    handleChange (event) {
        // This is NEVER fired
        doSomething()
    }
    render () {
        return (
            <select id='Fruits' onChange={this.handleChange.bind(this)}>
                <option value='A'>Apple</option>
                <option value='B'>Banana</option>
                <option value='C'>Cranberry</option>
            </select>
        )
    }
}

ReactDOM.render(<SelectComponent />, document.createElement('div'))

// Pragmatically change the selection
$('#Fruits').val('B').change()

However, without jQuery, it seems to work just fine. When I change the last line to:

const element = document.getElementById('Fruits')
element.value = value
element.dispatchEvent(new Event('change', { bubbles: true }))

the callback in ReactJS gets fired!

I cannot spot any difference. I thought that the code above is practically the same what jQuery does with .val('B').change(). Perhaps a jQuery ninja can give me a hint on this one?

like image 284
Roman Semko Avatar asked Jul 21 '16 05:07

Roman Semko


1 Answers

It doesn't work with jQuery change() because that doesn't trigger a "real" change event. It's a shortcut for .trigger('change') which says

A call to .trigger() executes the handlers in the same order they would be if the event were triggered naturally by the user

and

Although .trigger() simulates an event activation, complete with a synthesized event object, it does not perfectly replicate a naturally-occurring event.

I believe this was done in order to help support very old versions of IE that had different handling of events.

That's the why of it at any rate, since that's what you wanted to know. Just firing the event natively makes your tests less coupled with your implementation choices.

like image 111
ivarni Avatar answered Sep 28 '22 03:09

ivarni