Reputation: 123
I wrote the following component to embed a Pinterest widget in my React app:
import React, { Component } from 'react'
class PinterestWidget extends Component {
componentWillMount() {
const script = document.createElement('script')
script.async = true
script.type = 'text/javascript'
script['data-pin-build'] = 'doBuild'
script.src = '//assets.pinterest.com/js/pinit.js'
document.body.appendChild(script)
}
render() {
const { url } = this.props
return (
<a data-pin-do="embedPin" data-pin-build="doBuild" href={url}>
{url}
</a>
)
}
}
export default PinterestWidget
It works fine when the component mount the first time.
But when I navigate to another route and go back to this page, it doesn't render the widget anymore.
I tried to place the script in componentDidUpdate
, but no success.
PS: I searched for a component but the only one I found is react-pinterest which is not maintained for 2 years — and doesn't work in my app.
Can anybody help me?
Upvotes: 3
Views: 1893
Reputation: 4341
In my case, using the answer of @n33kos it works with useEffect
and so far every time (without checking whether it has appended the script or not). Here the <a>
link to pinterest exist in a markdown file that is injected as html
useEffect(() => {
const script = document.createElement('script')
script.async = true
script.type = 'text/javascript'
script.dataset.pinBuild = 'doBuild'
script.src = '//assets.pinterest.com/js/pinit.js'
document.body.appendChild(script)
if (window.doBuild) window.doBuild()
}, []) // only run once
Upvotes: 0
Reputation: 76
I found myself in the exact same position today. After wrestling with forks of that same react-pinterest
npm package I found a solution in this issue https://github.com/pinterest/widgets/issues/13.
It looks like you already got close by adding the data-pin-build="doBuild"
data attribute but you aren't calling doBuild()
when the user returns to the component after hitting a different route. Adding the data attribute instructs pinit.js
to add doBuild()
to the global scope but doesn't automatically call the function when you remount the component.
Try replacing your componentWillMount
function with something like this:
componentDidMount() {
if (!window.doBuild) {
this.preloadWidgetScript();
} else {
window.doBuild();
}
}
preloadWidgetScript = () => {
const script = document.createElement('script');
script.async = true;
script.dataset.pinBuild = 'doBuild';
script.src = '//assets.pinterest.com/js/pinit.js';
document.body.appendChild(script);
}
One other thing to note is the change from componentWillMount
to componentDidMount
, this is necessary to ensure the embed link is rendered before running doBuild()
.
Upvotes: 2