I’m trying to use the Facebook Javascript SDK in my Frontity theme, but I’m not sure what’s the best way to import it, and how to use it.
I don’t want it to slow down my page, so I want to import it async.
I need to call a function from it, after user navigates between posts ( FB.XFBML.parse();
).
I write down, how I implemented it, and I’m really happy for any feedback, or maybe somebody will benefit from it.
I created an FbSdkScript.js
file:
import React, { createContext, useContext, useState, useEffect } from 'react'
// Context.
export const FbSdkScriptContext = createContext()
// Create a custom hook to use the context.
export const useFbSdkScriptContext = () => useContext(FbSdkScriptContext)
// Provider of context.
const FbSdkScriptProvider = ({
children
}) => {
const [hasLoaded, setHasLoaded] = useState(false)
/**
* Extra security measure to check if the script has
* already been included in the DOM
*/
const scriptAlreadyExists = () =>
document.querySelector('script#fb-sdk') !== null
/**
* Append the script to the document.
* Whenever the script has been loaded it will
* set the isLoaded state to true.
*/
const appendSdkScript = () => {
const script = document.createElement('script')
script.id = 'fb-sdk'
script.src = '//connect.facebook.net/en_EN/sdk.js#xfbml=1&version=v10.0&autoLogAppEvents=1&appId=MY_APP_ID'
script.async = true
script.defer = true
script.crossOrigin = 'anonymous'
script.onload = () => setHasLoaded(true)
document.body.append(script)
}
/**
* Runs first time when component is mounted
* and adds the script to the document.
*/
useEffect(() => {
if (!scriptAlreadyExists()) {
appendSdkScript()
}
}, [])
return (
<FbSdkScriptContext.Provider value={{ hasLoaded }}>
{children}
</FbSdkScriptContext.Provider>
)
}
export default FbSdkScriptProvider
Then, added it to my components/index.js
:
... return(...
</Head>
<FbSdkScriptProvider>
.... // The conent of my site, including <Switch>
</FbSdkScriptProvider>
....
And I use it as the following in my posts, to have a Like button for each post:
import { useFbSdkScriptContext } from '../FbSdkScript'
const Post = ({ state, actions, libraries }) => {
const { hasLoaded } = useFbSdkScriptContext()
useEffect(() => {
if (hasLoaded) {
FB.XFBML.parse(document.getElementById('postContainer'))
}
}, [state.router.link, hasLoaded]) // I added state.router.link, so it's reparse my site after clicking to another post from this post.
...
// And here is the like button:
<StyledFBLike>
<div className='fb-like' data-href={post.link} data-width='' data-layout='button_count' data-action='like' data-size='large' data-share='true' />
</StyledFBLike>
...
}
export default connect(Post)
const StyledFBLike = styled.div`
width: 100%;
.fb-like, .fb-like iframe, .fb-like span { width: 100% !important; }