UNPKG

@exabytellc/utils

Version:

EB react utils to make everything a little easier!

70 lines (58 loc) 2.6 kB
import { useEffect, useState } from "react"; /** * Custom React hook to dynamically load an external CSS file or other linked resources. * * @param {string} id - Unique identifier for the link element. * @param {string} href - The URL of the resource to load. * @param {Object} [options] - Additional link loading options. * @param {string} [options.rel="stylesheet"] - The relationship between the document and the linked resource. * @param {string} [options.type="text/css"] - The MIME type of the linked resource. * @param {string} [options.media="all"] - The media attribute for the linked resource. * @param {Object} [options.attrs] - Additional attributes to set on the link element. * @param {boolean} [options.removeOnUnmount=false] - Whether to remove the link when the component unmounts. * * @returns {{ loaded: boolean, error: string | null }} - An object containing the link's load state and any error encountered. */ export default function useLinkLoader(id, href, options = {}) { const [loaded, setLoaded] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!href) return; // Check if the link already exists in the document if (document.getElementById(`link-loader-${id}`)) { setLoaded(true); return; } console.log('link', 'start', href); // Create a new link element const link = document.createElement("link"); link.id = `link-loader-${id}`; link.href = href; link.rel = options.rel ?? "stylesheet"; link.type = options.type ?? "text/css"; link.media = options.media ?? "all"; // Apply additional attributes if provided if (options.attrs) { for (let key in options.attrs) { link.setAttribute(key, options.attrs[key]); } } link.onload = () => { setLoaded(true); console.log('link', 'fetched', href); }; link.onerror = () => { console.log('link', 'failed', href); setLoaded(true); setError("Failed to load link!"); }; document.head.appendChild(link); // Cleanup function (removes link if `removeOnUnmount` is true) return () => { if (options.removeOnUnmount && document.head.contains(link)) { document.head.removeChild(link); } }; }, [id, href, options]); return { loaded, error }; };