Skip to content
Advertisement

Add Buy Me A Coffee Widget to React application

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.

Advertisement

Answer

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;
}
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement