Как программно вызвать <select>onChange в компоненте React с простым DOM Javascript? - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть простой компонент React:

state = {
  value: '',
};

render() {
  return <select onChange={this.handleChange} value={this.state.value}>
    <option value="">--</option>
    <option value="1">One</option>
  </select>;
}

handleChange = (e) => {
  this.setState({
    value: e.target.value,
  });
  console.log('Handling Change!!')
};

Я хочу иметь возможность запускать обработчик событий программно через обычный javascript или, в этом примере, jQuery.

$select = $('select');
$select.val('1');
// then
$select.trigger('change');
// or
$select.trigger('input');

Но ни один из них не вызывает обработчик onChange в компоненте React, и поэтому состояние не обновляется.

Мой вопрос: Как я могу вызвать onChange обработчик, использующий DOM и Javascript?

[править]

Чтобы пояснить немного подробнее, я монтирую компонент React следующим образом:

el = document.createElement('div')
ReactDOM.render(MySelect, el)

$select = $(el).find('select');
$select.val('1');
// then
$select.trigger('change');
// or
$select.trigger('input');

1 Ответ

0 голосов
/ 13 декабря 2018

Отвечая на мой собственный вопрос, для потомков.

Проблема, как оказалось, была двоякой.Но сначала немного предыстории:

События React

Система событий React прослушивает собственные события DOM, делегируя корневому узлу.то есть он не присоединяет слушателей к каждому элементу с onChange, а просто слушает в корневом документе события, которые всплывают через DOM.

Для тех, кто знаком с делегированными событиями jQuery, это было бы аналогично чему-то вроде

$(document).on('change', '.my-select', callback)

jQuery Events

Во-вторых, сам jQuery несколько «переопределяет»«Собственные события DOM переплетаются с собственной системой, и именно так вы можете создавать пользовательские события.

Решение ...

Как уже упоминалось, у меня было 2 проблемы и, следовательно, 2 решения.:

First

Из-за того, что jQuery использует собственную систему событий, события, запущенные с

$(select).trigger('change')

, не достигнут корневого прослушивателя событий React.Таким образом, мы работаем с ...

select.dispatchEvent(new Event('change', {bubbles, true}));

... но этого все еще недостаточно.

Секунда

События DOM всплывают изэлемент к корню документа. НО обратите внимание, что я никогда не прикреплял свой элемент к документу !! Событие change превращается в ... никуда!Опять же, он никогда не достигает обработчика событий React , зарегистрированного в документе .

Если я добавлю свой элемент в DOM следующим образом:

el = document.createElement('div')
ReactDOM.render(MySelect, el)
document.body.appendChild(el) // <-- attach to DOM

Сейчас событие достигает приемника событий React, и запускается оригинальный обработчик onChange в моем компоненте.

Надеюсь, это поможет любому, кто сталкивается с чем-то похожим.

пс.Я нашел документацию в этом файлеactjs полезной для понимания системы событий React: https://github.com/facebook/react/blob/master/packages/react-dom/src/events/ReactBrowserEventEmitter.js

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...