React: Uncaught Error: Invariant Violation: findComponentRoot: Unable to find element.

Created on 25 Jun 2015  路  5Comments  路  Source: facebook/react

I have this modal, in this component:

    var Modal = React.createClass({
        componentDidMount: function () {
            var modal = $('[data-remodal-id=modal]').remodal();
            $("button[type=submit]").on('click', function(e){
                e.preventDefault();
                modal.open();
            })
        },
        _handleVerify: function (e) {
            e.preventDefault();
            console.log('verifying....');
            //console.log(this.refs.vericationCode);
        },
        render: function () {
            return(
                <div className="remodal" data-remodal-id="modal">
                  <button data-remodal-action="close" className="remodal-close"></button>
                  <h1>Per attivare autenticazione OTP segui le istruzioni</h1>
                  <p>
                    Inserisci il tuo secret {this.props.secret} in Google authenticator, e inserisci il codice a 6 cifre prodotto qui
                  </p>
                  <br />
                  <form>
                    <div className="form-group">
                        <input type="text" className="form-control" id="vericationCode" placeholder="Enter Verification Code" ref="vericationCode" />
                    </div>
                    <button className="remodal-confirm" onClick={this._handleVerify}>Verica</button>
                  </form>
                </div>
                );
        }
    });

But when I click on the button, and trigger this._handleVerify, it gives me:

Uncaught Error: Invariant Violation: findComponentRoot(..., .0.1.1.1.4.1): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a>, or using non-SVG elements in an <svg> parent.

The component .0.1.1.1.4.1 it is the button. And this not happen if I remove the onClick event trigger on the element. I can't figure out what is the problem!

Most helpful comment

@ciaoben The point of using React is that you should not be modifying the DOM, so the 'correct' solution is to not use remodal. Instead, you should define your UI declaratively such that no DOM manipulations are needed.

If you're trying to popup a modal, I would recommend watching Ryan Florence's talk (http://conf.reactjs.com/schedule.html#hype) and playing with the portals demo located in demos/03-portals of https://github.com/ryanflorence/reactconf-2015-HYPE

All 5 comments

Curiosity: If I register a callback on the event in componentDidMount, it works.

Can understand why it doesn't work "the react way".

Do you know what the $.remodal() function is doing? Essentially what seems to be happening here is that your componentDidMount code is modifying the DOM. React jealously wants full control of manipulating the DOM. So a more proper rails way of doing these things would be using state and displaying a modal depending on state:

var Modal = React.createClass({
  getInitialState: function() {
    return { isModaled: false }
  },

  componentDidMount: function() {
    // this is not even ideal really..
    $("button[type=submit]").on('click', function(e){
      e.preventDefault();
      this.setState({isModaled: true});
    }.bind(this))
  },

  render: function() {
    if (this.state.isModaled) {
      return ...ModalDOM...;
    }

    // maybe return an empty div when not showing a modal?
    return <div></div>;
  }
});

@blainekasten is correct, remodal is likely modifying the dom. The problem is that React uses change tracking to optimize writes to the DOM, and if you change things from under React's feet, things break :/.

Our recommendation is that you avoid touching anything rendered by React; there shouldn't be a need to do so anyway (the whole point of React is that your render function is declarative and thus easier to reason about - if you start mutating things, you are back in the imperative world, so why use React at all?).

@ciaoben: Registering it as a callback as you suggested may have hidden/delayed the error, but you still would probably have received the same error later in your app development cycle (ie. next time React needed to reconcile changes to that component). Therefore, an app that does the dom manipulation as a callback is equally 'broken'.

Since this is not a bug in React, I'm going to close this issue. Feel free to continue to have the discussion here. For future reference: Questions about how to properly use React are probably better located on StackOverflow, since we use github issues to track bugs in React.

Thank you guys. You are right, I am again having difficulties to forget my old habits!

I will try the @blainekasten solution.

@jimfb But I don't uderstand where should I call the remodal() function, since it would modify anyway the DOM.

@ciaoben The point of using React is that you should not be modifying the DOM, so the 'correct' solution is to not use remodal. Instead, you should define your UI declaratively such that no DOM manipulations are needed.

If you're trying to popup a modal, I would recommend watching Ryan Florence's talk (http://conf.reactjs.com/schedule.html#hype) and playing with the portals demo located in demos/03-portals of https://github.com/ryanflorence/reactconf-2015-HYPE

Was this page helpful?
0 / 5 - 0 ratings