Import a javascript SDK and then use it

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; }

Hi @koli14 ,

You can directly use the <Script> React component available at the @frontity/components library

If you check the internal code of this component is doing more or less what your’re doing manually

Hope this helps

Thanks for the response @juanma !
I was not aware of the <Script> component, but it does not have an onload prop. How will I know, if it’s loaded already?

Hi @koli14,

Here you have the implementation of the <Script> component

As you can see is not a very complex implementation. Taking into account this implementation you can:

  • Replicate it and create your own <Script> component adding the onLoading event (via props) to the component
  • Open a Feature Discussion so this event is added to the official component
  • Open a PR with this new prop added to the official component or make this component ready so any extra props added toit are passed to the internal <script> tag

Thanks for the suggestions! PR is ready :slight_smile: .

1 Like