0

I have the following code:

Hook:

import { useEffect } from 'react';

const useScript = url => {
    useEffect(() => {
        const script = document.createElement('script');

        script.src = url;
        script.async = true;

        document.body.appendChild(script);

        return () => {
            document.body.removeChild(script);
        }
    }, [url]);
};

export default useScript;

Use:

useScript("script1.js")
useScript("script2.js")
useScript("script3.js")

How I would like to use it:

useScriptMulti("script1.js","script2.js","script3.js")

Can you give me a hand?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Paul
  • 3,644
  • 9
  • 47
  • 113
  • A hand with what? You haven't described a problem...? You have a hook, and you want to write another hook. Give it a try! **If** you get stuck, post a question with your attempt so people can help you with it. – T.J. Crowder Oct 12 '22 at 06:51
  • That said, a couple of observations: 1. There's basically no point in the cleanup callback there, removing the `script` element from the DOM doesn't do anything to the code it loaded. Once you've loaded a script, you can't unload it (in the general case; it's possible to write a script that can fully clean itself up). 2. There's no reason to use `async = true` on a `script` element you're adding dynamically after the main HTML parsing is complete, it has no effect. – T.J. Crowder Oct 12 '22 at 06:55
  • The same thing applies here: https://usehooks-ts.com/react-hook/use-script – Paul Oct 12 '22 at 07:47
  • Maybe there's some subtlety on the `async` thing I'm missing, though frankly I don't think so. Note that they *don't* remove the script element in the cleanup (presumably because there's no point). – T.J. Crowder Oct 12 '22 at 07:49
  • The removal of the listener because it is done what is it for in this case? – Paul Oct 12 '22 at 07:58
  • So the listener isn't fired if the hook is called with a different script during the period it's loading. Frankly, I wouldn't use anything like that `useScript` hook, it's using a hook for something that hooks just aren't meant for IMHO. – T.J. Crowder Oct 12 '22 at 08:03
  • Even if it is out of context, if you have time I can ask you how you would implement such a hook. – Paul Oct 12 '22 at 08:07
  • I really just wouldn't use a hook, so trying to shoehorn it into a hook I thought was valid would take more time than I have at the moment I'm afraid. Re `async`, it is irrelevant as I suspected: https://stackoverflow.com/questions/3408805/is-the-async-attribute-property-useful-if-a-script-is-dynamically-added-to-the – T.J. Crowder Oct 12 '22 at 08:33

1 Answers1

1

You can pass array of urls to hook.

const useScripts = urls => {
    useEffect(() => {

        const scripts = urls.map((url) => {
            const script = document.createElement('script');

            script.src = url;
            script.async = true;
            document.body.appendChild(script);
            return script;
        };

        return () => {
            srcipts.forEach((script) => document.body.removeChild(script));
        }
    }, [urls]);
};

export default useScript;

And then use it for one script useScripts(["script1.js"]) or for many useScripts(["script1.js", "script2.js"])

marvinav
  • 667
  • 5
  • 15