cbdeveloper
cbdeveloper

Reputation: 31495

Trying to run Ko-Fi widget inside a React component. Running <script> commands inside DIV

So, here's the script I have to run in order to implement a Ko-Fi widget on my website.

<script type='text/javascript' src='https://ko-fi.com/widgets/widget_2.js'></script>
<script type='text/javascript'>
  kofiwidget2.init('Buy me a coffe!', '#3c807c', 'XXXXXXXXXX');
  kofiwidget2.draw();
</script> 

My website is a Single Page App built with React, so here's what I'm doing.

1 - I moved the script that loads the widget_2.js to the <head> of my index.html file:

index.html

<script type='text/javascript' src='https://ko-fi.com/widgets/widget_2.js'></script>

Should I add the async to this script tag?

2 - I'm trying to load the rest inside my React component, but without success, so far:

I tried:

// NOTE: IT'S DISPLAYING AS MULTI-LINE HERE JUST TO MAKE IR MORE READABLE
return(
  <div dangerouslySetInnerHTML={{__html: 
    "<script type='text/javascript'>
       kofiwidget2.init('Buy me a coffee!', '#3c807c', 'XXXXXXXXXX');
       kofiwidget2.draw();
     </script>"
  }}>
);

And also:

return(
  <div>
    <script type="text/javascript">
      kofiwidget2.init("Buy me a coffee!", "#3c807c", "XXXXXXXXXX");
      kofiwidget2.draw();
    </script>
  </div>
);

And nothing seems to happen.

EXTRA INFO:

The kofiwidget2.draw(); method does the following:

draw: function () {
  document.writeln(style + html.replace("[color]", color).replace("[text]", text).replace("[id]", id));
}

It uses the document.writeln method. So I guess this should be run exactly where I need the button to be loaded. I.e: Inside the div.

SNIPPET (TRYING TO RUN A SCRIPT COMMAND INSIDE A DIV IN REACT)

function App() {
  return(
    <script type="text/javascript">console.log('TEST_1');</script>
  );
}

ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

Upvotes: 4

Views: 2092

Answers (2)

Chris
Chris

Reputation: 96

Solution for those using next.js

Add the following to layout.tsx or layout.js just before the closing tag for the body element.

Make sure to import Script from next/script at the top of the page.

  {/* Kofi Donations */}
<Script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js' strategy='beforeInteractive' />
<Script id="kofi-donations" strategy='beforeInteractive'>
   {`kofiWidgetOverlay.draw('<kofi_page_name>', {
    'type': 'floating-chat',
    'floating-chat.donateButton.text': 'Tip Me',
    'floating-chat.donateButton.background-color': '#5cb85c',
    'floating-chat.donateButton.text-color': '#fff'
   });`}
</Script>

Using the Script element and setting the strategy to beforeInteractive seems to be the key. If you find this to be acceptable my kofi page is here, but I'll settle for an upvote.

Upvotes: 0

JordyJordyJordyJordan
JordyJordyJordyJordan

Reputation: 147

There's not a lot of solutions to this on the internet (trust me, I searched forever). I wanted to use the interactive widget. Here was my solution. It's pretty similar to one of yours, but slightly modified. I'm working in nextjs as well.

add import Head from 'next/head'

At the top of your function component add

<Head>
     <script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js'/>
</Head>

Create a string to make your life easier:

const kofi = 
`<script>
  kofiWidgetOverlay.draw('pixelbakery', {
    'type': 'floating-chat',
    'floating-chat.donateButton.text': 'Tip Us',
    'floating-chat.donateButton.background-color': '#ff5f5f',
    'floating-chat.donateButton.text-color': '#fff'
  });
</script>`

inside your component somewhere:

 <div dangerouslySetInnerHTML={{ __html: kofi }} />

Upvotes: 1

Related Questions