Use react hooks to load third party library from CDN

May 01, 2023

Introduction

DevToolsDaily uses many different third party libraries on it's website.

There are 2 main reasons why we don't install all libraries:

  1. There are just way too many libraries we need to depend on, some of them are outdated, some of them conflict with each other; our build becomes slower. NPM hits memory limits etc.
  2. some WASM libraries like graphviz or python, are easier to load from NPM than to install locally.

Loading third party library in Gatsby

we wrote about that before in details - historically we've been using this script to load third party libraries:

export function new_script(src) {
  return new Promise(function(resolve, reject){
    if (typeof window !== "undefined") {
      var script = window.document.createElement('script');
      script.src = src;
      script.addEventListener('load', function () {
        resolve();
      });
      script.addEventListener('error', function (e) {
        reject(e);
      });
      window.document.body.appendChild(script);
    }
  })
};

then in our component we wait for that to be created, and can do processing. Usually we just do it using useEffect hooks.

e.g

 useEffect(() => {
  if (window.cv) {
    return;
  }
  var my_script = new_script('https://cdn.jsdelivr.net/npm/opencv.js-webassembly@4.2.0/opencv.js');
  my_script.then(() => {
      console.log("open cv is ready");
  });
}, []);

However that quickly became pretty repetitive. and page/component code loses readability because of that library loading code.

Using custom hooks to load a library

For each third party library we implement a small hook that wraps that repetitive code

const GRAPHVIZ = 'https://cdn.jsdelivr.net/npm/@hpcc-js/wasm/dist/graphviz.umd.js';

export function useGraphviz() {
    const [value, setValue] = useState(null);
    useEffect(() => {
        if (!window.graphviz) {
            new_script(GRAPHVIZ).then(() => {
                window["@hpcc-js/wasm"].Graphviz.load().then(graphviz => {
                    window.graphviz = graphviz;
                    setValue(graphviz);
                });
            });
        } else {
            setValue(window.pyodide);
        }
    }, []);
    return value;
}

then we can just use that in our component

const graphviz = useGraphviz();

useEffect(() => {
    if (graphviz) {
        graphviz.render... 
    }
}, [graphviz])

When hook sets the "value", the parent component is going to update and graphviz will be set.

We recently migrated all Graphviz pages to use these hooks, and plan to switch OpenCV, Python, JQ and SQL playgrounds to the same.

--

this blog post was originally published on https://www.devtoolsdaily.com/blog/react-hook-load-library/