UNPKG

@exabytellc/utils

Version:

EB react utils to make everything a little easier!

71 lines (59 loc) 2.61 kB
import { useEffect, useState } from "react"; /** * Custom React hook to dynamically load an external script. * * @param {string} id - Unique identifier for the script. * @param {string} src - The script URL to load. * @param {Object} [options] - Additional script loading options. * @param {boolean} [options.async=true] - Whether the script should load asynchronously. * @param {boolean} [options.defer=true] - Whether the script should defer execution. * @param {Object} [options.attrs] - Additional attributes to set on the script element. * @param {boolean} [options.removeOnUnmount=false] - Whether to remove the script when the component unmounts. * * @returns {{ loaded: boolean, error: string | null }} - An object containing the script's load state and any error encountered. */ export default function useScriptLoader(id, src, options = {}) { const [loaded, setLoaded] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!src) return; // Check if script already exists in the document if (document.getElementById(`script-loader-${id}`)) { setLoaded(true); return; } console.log('script', 'start', src); // Create a new script element const script = document.createElement("script"); script.id = `script-loader-${id}`; script.src = src; script.async = options.async ?? true; script.defer = options.defer ?? true; // Apply additional attributes if provided if (options.attrs) { for (let key in options.attrs) { script.setAttribute(key, options.attrs[key]); } } script.onload = () => { setLoaded(true); console.log('script', 'fetched', src); }; script.onerror = () => { console.log('script', 'failed', src); setLoaded(true); setError("Failed to load script!"); }; document.body.append(script); // Cleanup function (removes script if `removeOnUnmount` is true) return () => { if (options.removeOnUnmount) { const existingScript = document.getElementById(`script-loader-${id}`); if (existingScript) { document.body.removeChild(existingScript); } } }; }, [id, options.async, options.attrs, options.defer, options.removeOnUnmount, src]); return { loaded, error }; }