usehooks icon indicating copy to clipboard operation
usehooks copied to clipboard

useScript adds script to cache before it was loaded

Open Jony-Y opened this issue 5 years ago • 1 comments

Had this issue when I used it.

useScript adds the scripts to the cache before it was loaded. That means that if you in edge cases where you use the useScript twice in the same file. for example one of the scripts will return true before the script was actually loaded.

the fix is just to add to cache once the script loaded.

here is my version of the hook:

import { useEffect, useState } from 'react';

const cachedScripts = new Set();
function useScript(src) {
  const [loaded, setLoaded] = useState(false);
  const [error, setError] = useState(false);
  useEffect(() => {
    if (cachedScripts.has(src)) {
      setLoaded(true);
      setError(false);
    } else {
      const script = document.createElement('script');
      script.src = src;
      script.async = true;

      const onScriptLoad = () => {
        cachedScripts.add(src);
        setLoaded(true);
        setError(false);
      };

      const onScriptError = () => {
        if (cachedScripts.has(src)) {
          script.delete();
        }
        setLoaded(true);
        setError(true);
      };

      script.addEventListener('load', onScriptLoad);
      script.addEventListener('error', onScriptError);

      document.body.appendChild(script);

      return () => {
        script.removeEventListener('load', onScriptLoad);
        script.removeEventListener('error', onScriptError);
      };
    }
  }, [src]);

  return [loaded, error];
}

export default useScript;

Jony-Y avatar Jul 23 '19 08:07 Jony-Y

I'd also like to add that the initialState could check the cache:

  const [state, setState] = useState({
    loaded: cachedScripts.has(src),
    error: false,
  });

This means that code depending on a script can use it on first render if it's already in the cache.

AndrewIngram avatar Aug 19 '19 17:08 AndrewIngram