I am trying to create a component that renders the Buy Me A Coffee widget in some routes of my react single page application. This is my component so far:
class BuyMeACoffee extends React.Component {
    componentDidMount () {
         const script = document.createElement("script",);
         script.setAttribute('data-name','BMC-Widget')
         script.src = "https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js"
         script.setAttribute('data-id', 'boulderproblems');
         script.setAttribute('data-description', 'Thank you for your support!');
         script.setAttribute('data-message', 'This web is free to use. Do you want to help supporting it?');
         script.setAttribute('data-color',"#FF5F5F")
         script.setAttribute('data-position','right')
         script.setAttribute('data-x_margin','18')
         script.setAttribute('data-y-margin','18')
         script.async = true
         document.head.appendChild(script)
    }
    render(){
         return(null)
    }
}
When I inspect the page with the developer tools, the tag is at the end of the head section and everything seems correct but the widget doesn't show in the page.
Note: If I copy the script code in the head section of the index.html page:
<script data-name="BMC-Widget" src="https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js" data-id="boulderproblems" data-description="Thank you for your support!" data-message="This web is free to use. Do you want to help supporting it?" data-color="#FF5F5F" data-position="right" data-x_margin="18" data-y-margin="18"></script>
then it works perfectly. The problem is that in this case, the widget is shown for all routes. I have also tried react-helmet without success.
I finnally got it working. I post my solution here in case it is useful for someone. Not sure if it is the most elegant but it works. I slightly modified the original component so the script and widget is removed when the component is unmounted. Here is the component now:
class BuyMeACoffe extends React.Component {
    constructor(props){
        super(props)
        let script = document.createElement("script");
        script.setAttribute('data-name','BMC-Widget')
        script.src = "https://cdnjs.buymeacoffee.com/1.0.0/widget.prod.min.js"
        script.setAttribute('data-id', 'boulderproblems');
        script.setAttribute('data-description', 'Thank you for your support!');
        script.setAttribute('data-message', 'This web is free to use. Do you want to help supporting it?');
        script.setAttribute('data-color',"#FF5F5F")
        script.setAttribute('data-position','right')
        script.setAttribute('data-x_margin','18')
        script.setAttribute('data-y-margin','18')
        script.async = true
        //Call window on load to show the image
        script.onload=function(){
            var evt = document.createEvent('Event');  
            evt.initEvent('DOMContentLoaded', false, false);  
            window.dispatchEvent(evt);
        }
        this.script=script
    }
    componentDidMount () {    
        document.head.appendChild(this.script)
    }
    componentWillUnmount(){
        document.head.removeChild(this.script);
        document.body.removeChild(document.getElementById("bmc-wbtn"))
     }
    render(){
        return(null)
    }
}
Basically, after reading the buymeacoffee script I realized that they load the widget when the window is DOMContentLoaded event is fired. What I do is to fire this event manually after I insert the script.
Note: After doing this, I had to add a couple of styles because the widget was showing out of the screen. Maybe it was because of my layout. Anyway, here they are in case they you need them:
#bmc-wbtn{
    bottom: 15px;
}
#bmc-wbtn + div{
    bottom:15px;
}
                        A simpler way. 
You can create a react component like this.
Coffee.js
function Coffee() {
return (
<a
  className="buyButton"
  target="_blank"
  href="https://www.buymeacoffee.com/theshubhagrwl"
>
  <img
    className="coffeeImage"
    src="https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg"
    alt="Buy me a coffee"
  />
  <span className="coffeeButtonText">Buy me a coffee</span>
</a>
 );
}
Styles.css
.buyButton {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  color: #ffffff;
  background-color: #ff813f;
  border-radius: 5px;
  border: 1px solid transparent;
  padding: 0.5rem;
  font-size: 1rem;
  letter-spacing: 0.6px;
  box-shadow: 0px 1px 2px rgba(190, 190, 190, 0.5);
  font-family: cursive;
}
.buyButton:hover,
.buyButton:active,
.buyButton:focus {
  text-decoration: underline;
  box-shadow: 0px 1px 2px 2px rgba(190, 190, 190, 0.5);
  opacity: 0.85;
  color: #ffffff;
}
.coffeeImage {
  height: 2vh;
  box-shadow: none;
  border: none;
  vertical-align: middle;
}
.coffeeButtonText {
  margin-left: 15px;
  font-size: 0.8rem;
  vertical-align: middle;
}
This will give you easy customization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With