Как программно заполнить элементы ввода, созданные с помощью React?

Мне поручено сканировать веб-сайт, созданный с помощью React. Я пытаюсь заполнить поля ввода и отправить форму с помощью javascript-инъекций на страницу (селен или веб-просмотр на мобильных устройствах). Это работает как шарм на всех других сайтах + технологии, но React кажется настоящей болью.

так что вот пример кода

var email = document.getElementById( 'email' );
email.value = '[email protected]';

I значение изменяется на входном элементе DOM, но React не вызывает событие изменения.

Я пытался использовать множество способов, чтобы React обновил состояние.

var event = new Event('change', { bubbles: true });
email.dispatchEvent( event );

Безрезультатно

var event = new Event('input', { bubbles: true });
email.dispatchEvent( event );

не работает

email.onChange( event );

не работает

Я не могу поверить, что взаимодействие с React было настолько сложным. Я был бы очень признателен за любую помощь.

Спасибо

Ответ 1

React прослушивает событие input текстовых полей.

Вы можете изменить значение и вручную инициировать входное событие, а обработчик обработчика onChange будет запускать:

class Form extends React.Component {
  constructor(props) {
    super(props)
    this.state = {value: ''}
  }
  
  handleChange(e) {
    this.setState({value: e.target.value})
    console.log('State updated to ', e.target.value);
  }
  
  render() {
    return (
      <div>
        <input
          id='textfield'
          value={this.state.value}
          onChange={this.handleChange.bind(this)}
        />
        <p>{this.state.value}</p>
      </div>      
    )
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById('app')
)

document.getElementById('textfield').value = 'foo'
const event = new Event('input', { bubbles: true })
document.getElementById('textfield').dispatchEvent(event)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'></div>

Ответ 2

Это принятое решение, по-видимому, не работает в React> 15.6 (включая React 16) в результате изменений в дедупликации ввода и событиях изменений.

Вы можете увидеть обсуждение React здесь: https://github.com/facebook/react/issues/10135

И предлагаемый обходной путь здесь: https://github.com/facebook/react/issues/10135#issuecomment-314441175

Воспроизводится здесь для удобства:

Вместо

input.value = 'foo';
input.dispatchEvent(new Event('input', {bubbles: true}));

Вы бы использовали

function setNativeValue(element, value) {
  const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
  const prototype = Object.getPrototypeOf(element);
  const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;

  if (valueSetter && valueSetter !== prototypeValueSetter) {
    prototypeValueSetter.call(element, value);
  } else {
    valueSetter.call(element, value);
  }
}

а потом

setNativeValue(input, 'foo');
input.dispatchEvent(new Event('input', { bubbles: true }));

Ответ 3

что бы ситуация, если его выпадающий "выбрать". Я устал менять событие на "изменить", но получаю ошибку

Uncaught TypeError: Невозможно прочитать свойство 'set' из неопределенного