Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS - PopUp Component Error: Target container is not a DOM element

I'm trying here to make components in ReactJS to create PopUps but I get this error in react-with-addons.js :

Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.

Here's my code:

HTML :

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"> 
    <script type="text/javascript" src="react-0.13.3/build/react-with-addons.js"></script>
    <script type="text/javascript" src="react-0.13.3/build/JSXTransformer.js"></script>
    <script type="text/javascript" src="react-router/lib/umd/ReactRouter.js"></script>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="bootstrap/css/bootstrap-theme.min.css"/>

    <script type="text/javascript" src="jquery/jquery-1.11.1.min.js"></script>
    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>

    <title>WS-JAVA-REST</title>

    <style>
        .row { padding-top: 10px; }
    </style>
  </head>
  <body>
    <!-- contenu -->
    <div id="content">
        <script type="text/jsx" src="test.js"></script>
    </div>
  </body>
</html>

Javascript

/** @jsx React.DOM */

var clicked = function(){
  mountedPopup.setState({visible: true, pretendStateChanged: Date.now() });
  mountedComponent.setState({pretendStateChanged: Date.now() }) ;
}

var popupClicked = function(){
  mountedPopup.setState({visible: false, pretendStateChanged: Date.now() });
  mountedComponent.setState({pretendStateChanged: Date.now() }) ;
};

var Component = React.createClass({
  getInitialState: function() {
    return {pretendStateChanged: Date.now() };
  },
  render: function(){
    return React.DOM.div(null,
      React.DOM.a({onClick: clicked, href: "javascript:void(0);"}, "Show popup"),
      React.DOM.br(null),
      React.DOM.span(null, "State: " + this.state.pretendStateChanged)
    );
  }
});

var Popup = React.createClass({
  getInitialState: function() {
    return {visible: false, pretendStateChanged: Date.now()};
  },
  componentWillUpdate: function(nextProps, nextState){
    if (!this.state.visible && nextState.visible) {
      this.popUp();
    }

    /* closed by application */
    if (this.state.visible && !nextState.visible) {
      this.closePopUp();
    }
  },
  popUp: function(){
    var self  = this;
    var parent = this.getDOMNode().parentNode;
    $.magnificPopup.open({
      items: {
        src: parent,
        type: 'inline'
      },
      removalDelay: 30,
      callbacks: {
        afterClose: function() {
          if (self.state.visible){
            /* closed by user pressing ESC */
            self.setState({visible: false});
          }
        }
      }
    });
  },
  closePopUp: function(){
    $.magnificPopup.close();
  },
  render: function(){
    return React.DOM.div(null,
      React.DOM.a({
        onClick: this.props.onClickHandler,
        href: "javascript:void(0);"
      }, "Button inside popup"),
      React.DOM.br(null),
      React.DOM.span(null, "State: " + this.state.pretendStateChanged)
    );
  }
});

var mountedComponent = React.render(
  <Component/>,
  document.body.childNodes[1]
);

var mountedPopup = React.render(
  <Popup onClickHandler={this.popupClicked} />,
  document.body.childNodes[3]
);

So am I completely missing something ? Why am I getting this error ? Can somebody help me ?

like image 652
Lioru95 Avatar asked Sep 27 '22 13:09

Lioru95


1 Answers

The short answer to your question is that the original component hasn't loaded yet, so there is no target DOM node to load the Popup component. React.render has an optional third parameter for a callback that is fired when the render is complete. So the following should work for your case:

var mountedPopup;
var mountedComponent = React.render(
  <Component/>,
  document.body.childNodes[1],
  function() {
     mountedPopup = React.render(
        <Popup onClickHandler={this.popupClicked} />,
        document.body.childNodes[3]
     );
  }
);

However, as others have mentioned, there are a few big suggestions for this code as well:

  1. Definitely don't use document.body.childNodes[N] as a syntax
  2. You should probably avoid using libraries for popups where possible...jQuery and React don't always play well together
  3. You have this structured as two individual components and are using global variables and functions to tie them together. This would probably be better structured with the popup component as a child of the other component. In this way, you will be able to use the parent component to manage state and the popup can just respond to those changes. It will also allow you to encapsulate a lot of your code inside the parent component. If you do this, you won't need to refer to these components by their variable names, and won't even need to assign them variables. This is an anti-pattern and should probably be avoided.
  4. "this.popupClicked" probably won't work as expected. Since it is a global function, you can just refer to it as "popupClicked". Even better, you should eventually incorporate that as a method in your parent container (see above)
like image 88
Joe P Avatar answered Oct 02 '22 15:10

Joe P