How to programmatically fill input elements built with React?

帅比萌擦擦* 提交于 2019-11-27 17:35:40

问题


I'm tasked with crawling website built with React. I'm trying to fill in input fields and submitting the form using javascript injects to the page (either selenium or webview in mobile). This works like a charm on every other site + technology but React seems to be a real pain.

so here is a sample code

var email = document.getElementById( 'email' );
email.value = 'example@mail.com';

I the value changes on the DOM input element, but the React does not trigger the change event.

I've been trying plethora of different ways to get the React to update the state.

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

no avail

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

not working

email.onChange( event );

not working

I cannot believe interacting with React has been made so difficult. I would greatly appreciate any help.

Thank you


回答1:


React is listening for the input event of text fields.

You can change the value and manually trigger an input event, and react's onChange handler will trigger:

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:


This accepted solution appears not to work in React > 15.6 (including React 16) as a result of changes to de-dupe input and change events.

You can see the React discussion here: https://github.com/facebook/react/issues/10135

And the suggested workaround here: https://github.com/facebook/react/issues/10135#issuecomment-314441175

Reproduced here for convenience:

Instead of

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

You would use

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);
  }
}

and then

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


来源:https://stackoverflow.com/questions/40894637/how-to-programmatically-fill-input-elements-built-with-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!