3

I am using react-router. I have embedded the same external widget in two react components. The widget loads fine for the first time or when I refresh the page. The problem is when I change pages, the widget won't load anymore. Please look at my code:

var { Router, Route, IndexRoute, Link, browserHistory } = ReactRouter

var MainLayout = React.createClass({
  render: function() {
    return (
      <div className="app">
        <header className="primary-header"></header>
        <aside className="primary-aside">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/page1">Page1</Link></li>
            <li><Link to="/page2">Page2</Link></li>
          </ul>
        </aside>
        <main>
          {this.props.children}
        </main>
      </div>
      )
  }
})

var Home = React.createClass({
  render: function() {
    return (<h1>Home Page</h1>)
  }
})

var SearchLayout = React.createClass({
  render: function() {
    return (
      <div className="search">
        <header className="search-header"></header>
        <div className="results">
          {this.props.children}
        </div>
        <div className="search-footer pagination"></div>
      </div>
      )
  }
})

var PageOne = React.createClass({
  componentDidMount: function() {
    const plumxScript = document.createElement("script");
    plumxScript.src = "//d39af2mgp1pqhg.cloudfront.net/widget-popup.js";
    plumxScript.async = true;
    document.body.appendChild(plumxScript);
 },

  render: function() {
    return (
        <div
            href="https://plu.mx/plum/a/?doi=10.1371/journal.pone.0056506"
            className="plumx-plum-print-popup"
            data-hide-when-empty="true"
            data-popup="left"
            data-size="medium"
            target="_blank">
        </div>
      )
  }
})

var PageTwo = React.createClass({
  componentDidMount: function() {
    const plumxScript = document.createElement("script");
    plumxScript.src = "//d39af2mgp1pqhg.cloudfront.net/widget-popup.js";
    plumxScript.async = true;
    document.body.appendChild(plumxScript);
  },

  render: function() {
    return (
        <div
            href="https://plu.mx/plum/a/?doi=10.1371/journal.pone.0056506"
            className="plumx-plum-print-popup"
            data-hide-when-empty="true"
            data-popup="left"
            data-size="medium"
            target="_blank">
        </div>
      )
  }
})

ReactDOM.render((
  <Router>
    <Route path="/" component={MainLayout}>
      <IndexRoute component={Home} />
      <Route component={SearchLayout}>
        <Route path="page1" component={PageOne} />
        <Route path="page2" component={PageTwo} />
      </Route> 
    </Route>
  </Router>
), document.getElementById('root'))

Click on Page1 and the widget loads, click on Page2 and in theory the widget should reload but it doesn't. If I click again on Page1 the widget won't load.

Full code here: https://codepen.io/vh_ruelas/pen/MbgdOm

1 Answers1

1

The issue seems to be related to the script you're loading, not react-router. Apparently, it doesn't work as expected when you load it multiple times, which doesn't seem like a clean solution anyways.

If you load the script only once, you're left with the problem that the placeholder nodes that are rendered later won't be transformed automatically, since the script only initializes them when it is loaded (source). Luckily, the script adds a (apparently undocumented) function you can call to solve this: window.__plumX.widgets.popup.wireUp().

But there's another problem with the script in combination with React: It heavily modifies the DOM rendered by React, which causes all kinds of problems. There's a lot information about this, e.g., here. Apart from re-implementing the widget in React yourself, the best way seems to be to have React render a container <div> and then insert the widget node manually.

Here's a class that takes care of these two problems and seems to work the way you want:

var PlumXPopup = React.createClass({
  componentDidMount() {
    this.appendNode();
    this.appendScript();
  },

  appendNode: function() {
    const plumxNode = document.createElement("div");
    plumxNode.className = "plumx-plum-print-popup";
    plumxNode.setAttribute('href', 'https://plu.mx/plum/a/?doi=10.1371/journal.pone.0056506');
    plumxNode.setAttribute('data-hide-when-empty', 'true');
    plumxNode.setAttribute('data-popup', 'left');
    plumxNode.setAttribute('data-size', 'medium');
    plumxNode.setAttribute('target', '_blank');
    this.divNode.appendChild(plumxNode);
  },

  appendScript: function() {
    if (document.getElementById('plumx-script')) {
      if (window.__plumX) {
        window.__plumX.widgets.popup.wireUp();
      }
      return;
    }
    const plumxScript = document.createElement("script");
    plumxScript.id = 'plumx-script';
    plumxScript.src = "//d39af2mgp1pqhg.cloudfront.net/widget-popup.js";
    plumxScript.async = true;
    document.body.appendChild(plumxScript);
  },

  render: function() {
    var _this = this;
    return <div ref={function(ref) { _this.divNode = ref }} />
  }
});

You can use it instead of the placeholder <div> in PageOne and PageTwo, and also get rid of the script loading there. You might also want to add props to use when creating the placeholder node.

  • Thank you so much this solved the problem as I had originally posted it. I now have a different issue, if I embed multiple widgets in the same page they load fine initially, however, once I change pages and come back to the page only one widget loads instead of the multiple widgets. I have updated the code in [CodePen](https://codepen.io/vh_ruelas/pen/MbgdOm) in the link above to show the issue. I plan to have this set up of multiple widgets in one page because I am going to have widgets with different href attributes. – Victor Ruelas-Rivera Nov 07 '16 at 14:58
  • I solved the issue. I was originally embedding your PlumXPopup components inside a parent component (Page1), I moved the appendScript method to the parent component and it all seems to work now, [my code](https://codepen.io/vh_ruelas/pen/MbgdOm). Thanks so much for your help, you have helped me with this problem a lot I was struggling for a week! – Victor Ruelas-Rivera Nov 07 '16 at 16:12
  • Glad I could help :) This shouldn't be a problem actually; I'm guessing it's due to some bug in the widget, considering it uses an ancient version of jQuery. – Alexander Gundermann Nov 07 '16 at 19:26