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?

8
  • 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. Commented Oct 12, 2022 at 6: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. Commented Oct 12, 2022 at 6:55
  • The same thing applies here: usehooks-ts.com/react-hook/use-script Commented Oct 12, 2022 at 7: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). Commented Oct 12, 2022 at 7:49
  • The removal of the listener because it is done what is it for in this case? Commented Oct 12, 2022 at 7:58

1 Answer 1

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"])

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.