How do I get browser Autofill values to show up in my serialized React `Field` component data?

StackOverflow https://stackoverflow.com/questions/23432557

質問

I have a Form component that I am building in React and this form has some Field components as children. I am using these components to build a log in form that has an email address and password. My form has an onSubmit handler that serializes its children (Fields) and sends off an AJAX request.

Everything is working well in the normal case. But, when browsers like Chrome Autofill the form with my email address and password, the serialization doesn't pick up the values of the inputs.

Field currently looks something like this:

/** @jsx React.DOM */

var Field = React.createClass({
  serialize: function() {
    return { name: this.props.name, value: this.refs.field.state.value };
  },

  render: function() {
    return (
      <div>
        <label>
          {this.props.label}
          <input type={this.props.type} ref="field"
            name={this.props.name}
            defaultValue={this.props.value} />
        </label>
      </div>
    )
  }
});

How do I get the browser Autofill value to show up in my serialized Field data?

役に立ちましたか?

解決

State should flow in one direction, from the top layer down to the bottom. So reaching into a child element to get its state is a bad idea. To accomplish the serialization with this structure, you simply need to reach into the DOM to get the value of the input. In the code example above, the serialize method should be:

serialize: function() {
  return { name: this.props.name, value: this.refs.field.getDOMNode().value };
},

他のヒント

Using onChange event is the most common scenario to update whatever model property bound to a component, but you can also use onBlur to catch the values when the form is "auto-filled" by the browser.

var Input = React.createClass({
  getInitialState: function() {
    return {typed: ''};
  },
  onBlur: function(event) {
    this.setState({typed: event.target.value});
  },
  render: function() {
    return <div>
        <input type="text" onBlur={this.onBlur.bind(this)}/>
        You typed: <code>{this.state.typed}</code>
      </div>
  }
});

This is my solution using refs :) ..basically I trigger the change events manually for the first second..the reason behind is that every browser is handling autofill in a different way and this changes based on browser version..there is no way to cover this properly as of now

  componentDidMount () {
    let tries = 4;
    this.int  = setInterval(() => {
      tries--;
      if (tries === 0) {
        this._createChangeEvent();
        clearInterval(this.int);
      }
    }, 300);
  }

  _createChangeEvent = () => {
    if ("createEvent" in document) {
      const evt = document.createEvent("HTMLEvents");
      evt.initEvent("change", false, true);
      this.input.dispatchEvent(evt);
    } else {
      this.input.fireEvent("onchange");
    }
  };
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top