Facebook social comment plugin loads too slowly in react single page app - reactjs

I have a react class component where I need to load the facebook social comment plugin so that users can leave their comment. I've written the code like this:
This is the componentDidMount function:
componentDidMount() {
window.fbAsyncInit = () => {
window.FB.init({
appId: getConfigarationByKey('fb_app_id'),
xfbml: true,
version: 'v8.0'
})
window.FB.Event.subscribe('xfbml.render', this.stopSpinner)
}
var sdkSrc = ''
if (localStorage.getItem('lang') === 'en')
sdkSrc = '//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v8.0'
else sdkSrc = '//connect.facebook.net/bn_IN/sdk.js#xfbml=1&version=v8.0'
;(function (d, s, id) {
const fjs = d.getElementsByTagName(s)[0]
if (d.getElementById(id)) {
return
}
const js = d.createElement(s)
js.id = id
js.src = sdkSrc
fjs.parentNode.insertBefore(js, fjs)
})(document, 'script', 'facebook-jssdk')
if (window.FB && window.FB.XFBML) {
window.FB.XFBML.parse()
}
}
And when I change route, I clean up the comment plugin codes like this:
componentWillUnmount() {
if (window.FB) delete window.FB
document.getElementById('fb-root').outerHTML = ''
document.getElementById('facebook-jssdk').outerHTML = ''
}
And Finally I wrote the html as per it's suggested in the official docs
render() {
return (
<Card>
<CardContent>
<div
className="fb-comments"
data-colorscheme="dark"
data-href={window.location.href}
data-numposts="5"
data-width="100%"
></div>
</CardContent>
</Card>
)
}
That is all. The comment plugin loads and works fine, but it takes almost 30 seconds to load on the page which is a very bad user experience. Can anyone please help me why it is taking this much time to load ? And how I can improve it. Thank you.

Related

Ionic Native contacts spent a lot of time and blocks UI

I am developing with Ionic + Capacitor + React and I need to read all contacts numbers.
Using ionic-native/contacts in this way:
import { Contacts, ContactFindOptions } from '#ionic-native/contacts';
...
loadContacts() => {
this.setState(
{
loading: true,
},
() => {
var contacts = new Contacts();
const desiderFields = ['phoneNumbers'];
var options = new ContactFindOptions();
options.filter = '';
options.multiple = true;
options.hasPhoneNumber = true;
contacts.find(desiderFields, options).then((result) => { ... } );
});
}
componentDidMount() {
this.loadContacts();
}
But as soon as loadContacts start reading contacts the UI blocks and not even the state has time to render to show the loader.
Plus, the it is very slow importing contacts, showing repeatedly Fetching in bulk 250 contacts!.
I know that cordova-plugin-contacts is deprecated but I can't believe that those not exists valide alternatives to this fundamental feature.
Can't find solution.
I found this cordova plug-in that saved my life:
https://github.com/dbaq/cordova-plugin-contacts-phone-numbers

How to replace HTML images with GatsbyJS responsive images?

I am querying data from the Directus CMS in GatsbyJS using the Directus 7 source like so:
query {
allDirectusBlog {
edges {
node {
name
body
}
}
}
}
My problem is that body is actually raw HTML with image tags pointing to my Directus server. Which is normally fine, however these images are extremely large and take a fair amount of time to load even over WiFi. Is there a way to replace these <img> tags with Gatsby responsive images at build time?
I've create a function using html-react-parser with the post content of WordPress to replace all img with of Gatsby and the image provide in the static folder.
If you want a way to do that, this is a part of my code that you'll be able to adapte for your project (this is a WIP function, but work well)
export const ParsePostContentHTML = dataContent => {
let indexKeyImg = 234;
const ParsedHTML = Parse(dataContent, {
replace: function(domNode) {
if(domNode.name === 'img') {
const fluidImg = data.allWordpressWpMedia.edges.filter(media => {
return media.node.source_url === domNode.attribs.src
})
if(fluidImg.length > 0) {
let srcMedia = (fluidImg[0].node.localFile.childImageSharp)
? fluidImg[0].node.localFile.childImageSharp.fluid
: fluidImg[0].node.localFile.publicURL
indexKeyImg++
if(fluidImg[0].node.localFile.childImageSharp) {
return (
<Img
key={indexKeyImg}
fluid={srcMedia}
className={`${domNode.attribs.class} gatsby-rendered-img`}
alt={fluidImg[0].node.alt_text}
/>
)
} else {
return (
<img
key={indexKeyImg}
src={srcMedia}
className={`${domNode.attribs.class} gatsby-rendered-img`}
alt={fluidImg[0].node.alt_text}
/>
)
}
}
}
}
})
return ParsedHTML
}
You just have to import this function in your components/template and using it with ParsePostContentHTML(YourPostContent)
Hope that help you!

Window.ga is undefined in Firefox when using Google Tag Manager in React

I have a standard React project and am using Google Tag Manager to load analytics on the page. I have the Google Tag Manager in the head of the index.html. I have some code to retrieve the clientId from the window.ga object and then populate it into a field in my state on one of my components called "gaClientId". I have a method that retrieves the clientId and gets called in componentDidMount(). This works as expected in Chrome and IE but not Firefox for some odd reason. Not exactly sure what the issue is. I have checked to make sure that firefox is not blocking the tracker and have noticed in the console that if I console.log(window.ga) I get the undefined message before Google Tag Manager loads. Didn't know if that is where the issue is. Here is my method:
getGAClientId() {
try {
const tracker = ga.getAll()[0];
let clientId = tracker.get("clientId");
this.setState({ gaClientId: clientId });
} catch (e) {
return null;
}
}
and here is my state in the component:
this.state = {
firstname: '',
lastname: '',
email: '',
gaClientId: ''
};
This is being set to the value of a hidden form field like this:
<input type="hidden" value="this.state.gaClientId" name="gaClientId" />
Here is the head of my index.html just to show you:
<head>
<!-- Google Tag Manager -->
<script>
(function(w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
"gtm.start": new Date().getTime(),
event: "gtm.js"
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != "dataLayer" ? "&l=" + l : "";
j.async = true;
j.src = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, "script", "dataLayer", "GTM-xxxxxxx");
</script>
<!-- End Google Tag Manager -->
</head>
Any help with this is appreciated. Thanks!
Figured it out! I needed to add a setTimeout() to my getGaClientId() call in my componentDidMount. I just updated the code to the below to fix it.
componentDidMount() {
setTimeout(() => {
this.getGAClientId();
}, 2000);
}
I guess the load order of when Google Analytics was loading to when my method was being called was off.

Amazon Native Shopping Ads (Search Ads) in React

https://affiliate-program.amazon.com/welcome/getstarted_fifth
Is it possible to introduce Amazon Native Shopping Ads' 「Search Ads 」 into the React project?
I attempted trial and error, but I do not think that it is probably going well with global variable issues.
Here is how I did it.
If your Native Shopping Ads code looks like this:
<div id="amzn-assoc-ad-xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></div><script async src="//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></script>
In your component,
componentDidMount () {
const script = document.createElement("script");
script.src = "//z-na.amazon-adsystem.com/widgets/onejs?MarketPlace=US&adInstanceId=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
script.async = true;
document.body.appendChild(script);
}
In your JSX
<div id="amzn-assoc-ad-xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"> </div>
Yes it works very well with this logic but I made a better version out of it.
In your React Hook
useEffect(() => {
const script = document.createElement('script')
script.text = `amzn_assoc_ad_type = "banner"; amzn_assoc_marketplace = "amazon"; amzn_assoc_region = "US"; amzn_assoc_placement =
"assoc_banner_placement_default"; .................`
const script2 = document.createElement('script')
script2.src = '//z-na.amazon-adsystem.com............'
script2.async = false
const amazonAdd = document.querySelector('#amzn_assoc_ad_div_assoc_banner_placement_default_0')
if (amazonAdd) {
amazonAdd.appendChild(script)
amazonAdd.appendChild(script2)
}
}, [])
In your JSX
<div id="amzn_assoc_ad_div_assoc_banner_placement_default_0" />
You need to use the exact same id than amazon uses. Take a look in your DOM to see how this amazon script append a div in your DOM, get its id and use the same in your JSX div

Add google trends in react

How do you add components such as charts in google trends in reactjs?
componentDidUpdate() {
const that = this
const keyword = "your keyword"
conts script = document.createElement("script")
script.src = "https://ssl.gstatic.com/trends_nrtr/760_RC08/embed_loader.js"
script.async = true
ReactDOM.findDOMNode(this.refs.trendsWrapper1).appendChild(script)
script.onload = function () {
trends.embed.renderExploreWidgetTo(ReactDOM.findDOMNode(that.refs.trendsWrapper1), "TIMESERIES", {"comparisonItem":[{"keyword":keyword,"geo":"","time":"today 5-y"}],"category":0,"property":""}, {"exploreQuery":"q=%2Fm%2F0rfgxy2","guestPath":"https://www.google.co.uk:443/trends/embed/"})
}
}
I tried this and didn't work. Please try to suggest a much easier method than this as well.
You need to load the embed_loader script out side of react (like any other 3rd lib code)
At the component, run the trends.embed command.
var Trends = React.createClass({
render: function() {
trends.embed.renderWidget("US_cu_mqCQGFwBAABWOM_en",
"fe_line_chart_309e703b-7d68-4baa-8dc9-c12e2f9defc3",
{"guestPath":"https://trends.google.com:443/trends/embed/"});
return (
<div>must return something :/</div>
)}
});
Here is an example

Resources