Как программно заполнить элементы ввода, созданные с помощью 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' из неопределенного