user1438611
user1438611

Reputation:

React-Bootstrap Popover with Form field Validation

I was trying to play off of the example code shown here in order to have an overlay trigger that displays a popover upon invalid username field regex for my form component. I'm getting the classic Cannot update during an existing state transition (such as within "render"). Render methods should be a pure function of props and state. error upon trying to execute this code:

var UserField = React.createClass({
  getInitialState: function() {
    return {
      value: ''
    };
  },

  getValue: function() {
    return this.refs.input.getValue();
  },

  validationState: function() {
    let valueCode = this.state.value;
    if (valueCode.length > 0) {
      switch (valueCode.match(/^[A-Za-z0-9_-]+$/)) {
        case null:
          this.refs.userHint.show();
          return 'warning';
          break;

        default:
          this.refs.userHint.hide();
          return '';
          break;
      }
    }
  },

  handleChange: function() {
    this.setState({
      value: this.refs.input.getValue()
    });
  },

  render: function() {
    return (
      <OverlayTrigger
        ref="userHint"
        trigger="manual"
        placement="right"
        overlay={<Popover title='Invalid Username Format'>
                   <strong>Warning!</strong> Valid user credentials only contain alphanumeric characters, as well as heifens and underscores.
                 </Popover>
        }
      >
        <Input
          type = 'text'
          value = {this.state.value}
          label = 'Username'
          bsStyle = {this.validationState()}
          ref = 'input'
          groupClassName = 'input-group'
          className = 'form-control'
          onChange = {this.handleChange}
        />
      </OverlayTrigger>
    );
  }
});

Any help on this is very much appreciated, as always. Thank you.

Upvotes: 2

Views: 3335

Answers (1)

sedge
sedge

Reputation: 330

If I was developing this I would do it differently, with the Input managing it's own validation and exposing whether it's valid or not through its state (accessible through refs).

Without changing your approach, this should work better because it won't trigger changes in state of the parent component until the overlay has been shown or hidden:

validationState: function() {
  let valueCode = this.state.value;
  if (valueCode.length > 0) {
    switch (valueCode.match(/^[A-Za-z0-9_-]+$/)) {
      case null:
        return 'warning';
        break;

      default:
        return '';
        break;
    }
  }
},

handleChange: function() {
  let valueCode = this.refs.input.getValue();

  if (valueCode.length > 0) {
    switch (valueCode.match(/^[A-Za-z0-9_-]+$/)) {
      case null:
        this.refs.userHint.show();
        break;

      default:
        this.refs.userHint.hide();
        break;
    }
  }
  this.setState({
    value: valueCode
  });
},

Upvotes: 2

Related Questions