Using Coral Talk with React and Meteor
Asked Answered
C

2

10

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.

Changchun answered 25/7, 2018 at 23:7 Comment(0)
P
4

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>
    );
  }
}
Pacification answered 28/7, 2018 at 19:27 Comment(2)
Thank you River Tam! I tried your first suggestions but I couldn't make them work for me. However, React-Helmet did the trick! I have been spinning in circles trying to get this to render properly. Thank you so much!Changchun
Sorry they didn't work for you -- would love to know why. But glad React Helmet worked for you. =)Pacification
T
0

Answer taken from another forum, I'm posting it here to add to the discussion and help anyone else having the same issue in the future:

you can not call Coral.Talk.render from the onload event like that. there is no check for the component to be rendered, so you are telling coral talk to render to an element that is not there. you have a timing issue most likely.

what you have to do is in your render method put a ref prop on the comments div like this

this is what gotCommentsDiv could be...

gotCommentsDiv(el) { if (el) Coral.Talk.render(el, {talk: 'http://127.0.0.1:3000/'}); }

Trishatriskelion answered 29/7, 2018 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.