0

I have two react classes both have render function that returns forms with a button. In class A, I had to import class B so i can use form from class B.

My problem: When I clicked the inner button, the outer button gets triggered as well but I only want the inner submit button to work.

My attempt: I checked the console and found out that it is giving me a warning: validateDOMNesting: form cannot appear as a descendant of form.

I did the research and thought that the problem may due to the nested form . So I found out a workaround from SO by changing the <form></form> in the class B to <div></div>, so it is no longer a form. Now it does not give me error on console, but the problem still remains: if I click the inner button, the outer button got triggered as well which invoked two functions in total.

Where I need help: I really want to figure out what cause this behavior(I am thinking maybe changing the tag does not change the nested form problem or maybe the way how I referencing the other class is not completely right)

My code:(Please notice that I simplified it)

var classA = React.createClass({
  render: function() {
    return (
      <div>
        <form
          className={this.props.className}
          id={this.props.controllerSingular + '_form'}
          onSubmit={this.handleSubmit}
          ref="some_form"
        >
          <FieldSet>
            <ClassB id={this.state.id} />
          </FieldSet>
          <button onClick={this.submit} className="btn btn-primary">
            Save
          </button>
        </form>
      </div>
    )
  },
})

var classB = React.createClass({
  render: function() {
    return (
      <div>
        <button id="some_ID" className="some_name" onClick={this.handleRegAdd}>
          Add
        </button>
      </div>
    )
  },
  handleRegAdd: function() {
    var that = this
    var regLines = this.state.regulation
    regLines.push({
      reg_id: null,
      Type: $('.reg-type-select span.Select-value-label').text(),
      id: that.props.id,
      Hours: null,
      Minutes: null,
      Days: '',
      Start: null,
      End: null,
    })

    this.setState({
      regulations: regLines,
    })
  },
})

when I clicked the button from class B, which should only trigger function "handleRegAdd". However, it also triggered submit function in class A

BonsaiOak
  • 27,741
  • 7
  • 30
  • 54
ZpfSysn
  • 807
  • 2
  • 12
  • 30
  • Unfortunately, the simplification has left out things that are critical to understanding the problem. Where is `handleRegAdd` defined? FYI, you don't need to wrap the button in a div if nothing else is inside that div. – Sia Oct 27 '17 at 19:01
  • But also, the answer is probably just that you are using a `button` and the default type for a button is `submit`. See this post https://stackoverflow.com/questions/2825856/html-button-to-not-submit-form – Sia Oct 27 '17 at 19:03
  • @Sia I have updated my handleRegAdd. It basically set the state, that's all. If the logic of code above looks correct, that means the error is from something else. I will look into that. Maybe it is not caused by something I thought. – ZpfSysn Oct 27 '17 at 19:06

2 Answers2

2

The error is not related to the validateDOMNesting warning.

Button clicks (and other DOM events) bubble up the component tree. That means that clicking on the button will trigger the onClick event for all parent components as well.

You can stop the bubbling by calling event.preventDefault() in your event handler. It might look like this:

handleRegAdd: function(event) {
  event.preventDefault()

  // continue with the rest of your code
}
BonsaiOak
  • 27,741
  • 7
  • 30
  • 54
  • Is there anything else that will cause the similar problem? Is there a name for this specific structure in react? Now I am really curious about the "bubble up the component tree" stuff since I feel like I missing a react knowledge and I wanna read more about it, but I cant seem to find the reading about it. – ZpfSysn Oct 27 '17 at 19:35
  • This (event bubbling) isn't specific to React. You can read about it in this answer: https://stackoverflow.com/a/4616720/1424833 – Matt Holland Oct 27 '17 at 20:32
0

The default type for a button is submit, so to have the button not perform the form's onSubmit action, simply change the type to button:

<button type="button" id="some_ID" className="some_name" onClick={this.handleRegAdd}>
  Add
</button>

I mentioned this in my comment, and it's also covered here in this SO question: HTML button to NOT submit form

Sia
  • 8,894
  • 5
  • 31
  • 50