Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Coral Talk with React and Meteor

I am really struggling with implementing The Coral Talk Project commenting system into my app. I am attempting to implement it into a project that is primarily Meteor and React. It's on GitHub

I think the main issue is that this is the first time I have needed to use a Script Tag in React.
I have attempted doing it via the dom in componentDidMount, by using dangerouslySetHtml, tried using this suggestion, and a couple different packages for loading scripts, but only the div and src display when inspected, but not the script content on the page itself. The onload functionality of it seems to not be firing.

I have confirmed the server and embed code function properly by setting up another much more simple Node/Express app.
Here is the code I am trying to embed into my React site:

<div id="coral_talk_stream"></div>
<script src="http://127.0.0.1:3000/static/embed.js" async onload="
  Coral.Talk.render(document.getElementById('coral_talk_stream'), {
    talk: 'http://127.0.0.1:3000/'
  });
"></script>

Any suggestions would be greatly appreciated.

like image 622
Christopher W Avatar asked Jul 25 '18 23:07

Christopher W


1 Answers

I would do this outside of React entirely. So put that in your main.html. I would then, rather than having the onload just be

Coral.Talk.render(document.getElementById('coral_talk_stream'), {
  talk: 'http://127.0.0.1:3000/'
});

change it to

window.renderCoralTo = function (id) {
  Coral.Talk.render(document.getElementById(id), {
    talk: 'http://127.0.0.1:3000/'
  });
}

Then, in your component, do this:

class CoralTalk extends Component {
  static divId = 'coral_talk_stream';

  shouldComponentUpdate() {
    return !this.rendered; // Stops the div from being remounted
                           // shouldn't be necessary, but a minor precaution
  }

  renderCoral = div => {
    if (!this.rendered && div != null) {
      window.renderCoralTo(CoralTalk.divId);
    }
  };

  render() {
    return (
      <div id={CoralTalk.divId} ref={this.renderCoral} />
    );
  }
}

I'm not 100% this will work, but it seems likely that it would.

If you need to have the script tag only load sometimes (as in on some pages), you can use something like React Helmet or just Portals to conditionally render the script tag to your head.

A 100% untested example using Portals:

class DynamicScript extends Component {
  render() {
    return React.createPortal(
      <script {...this.props} />,
      document.getElementsByTagName('head')[0]
    );
  }
}

class CoralTalk extends Component {
  static divId = 'coral_talk_stream';

  shouldComponentUpdate() {
    return !this.rendered; // Stops the div from being remounted
                           // shouldn't be necessary, but a minor precaution
  }

  render() {
    this.rendered = true;
    return (
      <Fragment>
        <ConditionalScript src="http://127.0.0.1:3000/static/embed.js" async onload={`
          Coral.Talk.render(document.getElementById('${CoralTalk.divId}'), {
            talk: 'http://127.0.0.1:3000/'
          });
        `} />
        <div id={CoralTalk.divId} />
      </Fragment>
    );
  }
}
like image 176
River Tam Avatar answered Nov 20 '22 11:11

River Tam