Meteor-Semantic-React - How To Handle Dynamic DOM Manipulation


#1

Hey All,
Was wondering how I would go about handling this issue I am having. What I have thus far is using Semantic-UI, React, and Meteor together using the main packages from Atmosphere.

I have gotten pretty deep into the application and things are working great overall but I’ve run into an issue which is causing me some major headache. From what I can see, the issue is something that has plagued many people across the board.

I do see some options exists in atmosphere but I believe they all are based on the non-official react binding which basically makes that pointless for me.

Essentially I am trying to build a form in a modal that dynamically displays data based on the previous selections. I thought this would be really easy with these frameworks but it has proven to be a very difficult task thus far. This is due to the movement of the modal to the body by React. I have read from tons of other people to use a “Portal” or something to make this work and all the examples pretty much do nothing at all!

Any ideas on where I can look or how to best handle this with Meteor?


#2

I’m not clear from your post what your exact problem is, perhaps post some code to show the issue? - However, if you’re having trouble with Semantic UI moving the modal markup’s position within the DOM (thus interfering with React’s rendering tree) which is what it sounds like, within your call to .modal() to initialise the modal you need to add detachable: false to the options. So, if you’re doing all that in your componentDidMount() function it would look like this…

componentDidMount() {
    let self = this.getDOMNode()        
    $(self).modal({
        detachable: false
    })
}

EDIT: Sorry, first version of this reply said you need to render the modal’s HTML outside of React’s tree, this isn’t the case (I went to check my actual code) - just setting the detachable: false will stop the DOM manipulation.


#3

Thank you for your reploy firegoby! Your method seems a bit easier, so I am definitely going to try that out as well, but I figured I would let everyone know incase they come across the need to build React Portals.

I figured this out by studying the “portal” concept. Unfortunately the results of my searches yielded answers which appeared to be incorrect. It wasn’t until I watched the actual video from the facebook developer conference that I figured everything out.

Essentially you need to tell react to stop rendering, then when it says it accepts that, render a new react component (which will then be outside of the react app itself but will still be part of the react rendering tree).

So in my App.jsx:

<Portal className={'ui long modal dash scrolling'} isOpen={this.state.openConfig}>
     <SetupModal />
</Portal>

Then in my Portal.JSX:

  componentDidMount() {
        console.log('Portal Mounted');
        this.portal = document.createElement('div');
        document.body.appendChild(this.portal);
        this.portal.setAttribute("class", this.props.className);
        this.modal = $(this.portal).modal({
              onApprove: this.processCommand,
              blurring: true,
              observeChanges: true
        });
  },

 componentDidUpdate() {                
        React.render(this.props.children, this.portal);
        if (this.props.isOpen) {
              console.log('Show the Portal!');
              this.modal.modal('show');
        } else {
              console.log('Hide the Portal!');
              this.modal.modal('hide');
        }
  },

  componentWillUnmount() {
        document.body.removeChild(this.portal);
  },

 render() {
        console.log('Creating a React Portal!');
        return null;
  }