How to load script in specific page in gatsby

Viewed 1038

Hello.

I recently got stuck with pretty important thing on my gatsby site.
I have to import script from other site cause it is providing map widget. This is the widget from polish delivery company and it is only available under link https://mapa.ecommerce.poczta-polska.pl/widget/scripts/ppwidget.js.

It is activated by a function window.PPWidgetApp.toggleMap(). Problem is when i try to activate, html and css markup from widget are showing but map coming from js it is not.

Here is how I'm loading the script:

{
  resolve: "gatsby-plugin-load-script",
  options: {
    src:
      "https://mapa.ecommerce.poczta-polska.pl/widget/scripts/ppwidget.js",
  },
},

When I'm on specific route where I'm using this widget and i refresh the page everything is working properly. So I'm guessing problem is that when this script is loaded in index it gets cached somehow by gatsby and most of the important features are not working. So can I load the script only when I'm on let's say route /delivery ? Or is there another, better way to load this script that may work fine ?

Link to github repo with this problem: https://github.com/Exanderal/gatsby-problem

1 Answers

The easiest, native and built-in way to achieve is using <Helmet> component. Basically, this component embeds everything that is inside in your <head> tag.

The problem using it is that if you need to activate or to wait for its loading to make some actions (like window.PPWidgetApp.toggleMap() in your case), it could be kind of buggy since sometimes it may load properly but sometimes not. I will show you different approaches to check which one fits you better.

  1. <Helmet> approach:

    <Helmet>
      <script src="https://mapa.ecommerce.poczta-polska.pl/widget/scripts/ppwidget.js"/>
    </Helmet>
    

    As I said, this workaround may work for standalone scripts, but if you need to perform actions or wait for its loading it may not work. The next approach should fit you.

  2. Custom script loading approach:

     const addExternalScript = (url, callback) => {
       const script = document.createElement('script');
       script.src = url;
       script.async=true;
       script.onload = callback;
       document.body.appendChild(script);
    };
    
    useEffect(()=>{
     addExternalScript("https://mapa.ecommerce.poczta-polska.pl/widget/scripts/ppwidget.js",window.PPWidgetApp.toggleMap())
    },[])
    

    Basically, you are setting a custom function (addExternalScript) that creates the same script tag as the first approach and embeds the passed URL as a first function parameter. The second parameter is the callback function to trigger once it's loaded in the onload function.

    Everything it's triggered in the useEffect function with empty deps ([]). The useEffect is a hook (available in React version ^16) that is triggered once the DOM tree is loaded, in this case, it's a nice way to ensure that the window object is properly loaded and set to avoid some common issues in Gatsby using global objects.

Related