@darwish/hooks-core
Version:
112 lines (111 loc) • 4.45 kB
JavaScript
import { useEffect, useRef, useState } from "react";
// {[path]: count}
// remove external when no used
var EXTERNAL_USED_COUNT = {};
var loadScript = function (path, props) {
if (props === void 0) { props = {}; }
var script = document.querySelector("script[src=\"".concat(path, "\"]"));
if (!script) {
var newScript_1 = document.createElement("script");
newScript_1.src = path;
Object.keys(props).forEach(function (key) {
newScript_1[key] = props[key];
});
newScript_1.setAttribute("data-status", "loading");
document.body.appendChild(newScript_1);
return {
ref: newScript_1,
status: "loading",
};
}
return {
ref: script,
status: script.getAttribute("data-status") || "ready",
};
};
var loadCss = function (path, props) {
if (props === void 0) { props = {}; }
var css = document.querySelector("link[href=\"".concat(path, "\"]"));
if (!css) {
var newCss_1 = document.createElement("link");
newCss_1.rel = "stylesheet";
newCss_1.href = path;
Object.keys(props).forEach(function (key) {
newCss_1[key] = props[key];
});
// IE9+
var isLegacyIECss = "hideFocus" in newCss_1;
// use preload in IE Edge (to detect load errors)
if (isLegacyIECss && newCss_1.relList) {
newCss_1.rel = "preload";
newCss_1.as = "style";
}
newCss_1.setAttribute("data-status", "loading");
document.head.appendChild(newCss_1);
return {
ref: newCss_1,
status: "loading",
};
}
return {
ref: css,
status: css.getAttribute("data-status") || "ready",
};
};
var useExternal = function (path, options) {
var _a = useState(path ? "loading" : "unset"), status = _a[0], setStatus = _a[1];
var ref = useRef();
useEffect(function () {
if (!path) {
setStatus("unset");
return;
}
var pathname = path.replace(/[|#].*$/, "");
if ((options === null || options === void 0 ? void 0 : options.type) === "css" ||
(!(options === null || options === void 0 ? void 0 : options.type) && /(^css!|\.css$)/.test(pathname))) {
var result = loadCss(path, options === null || options === void 0 ? void 0 : options.css);
ref.current = result.ref;
setStatus(result.status);
}
else if ((options === null || options === void 0 ? void 0 : options.type) === "js" ||
(!(options === null || options === void 0 ? void 0 : options.type) && /(^js!|\.js$)/.test(pathname))) {
var result = loadScript(path, options === null || options === void 0 ? void 0 : options.js);
ref.current = result.ref;
setStatus(result.status);
}
else {
// do nothing
console.error("Cannot infer the type of external resource, and please provide a type ('js' | 'css'). " +
"Refer to the https://ahooks.js.org/hooks/dom/use-external/#options");
}
if (!ref.current) {
return;
}
if (EXTERNAL_USED_COUNT[path] === undefined) {
EXTERNAL_USED_COUNT[path] = 1;
}
else {
EXTERNAL_USED_COUNT[path] += 1;
}
var handler = function (event) {
var _a;
var targetStatus = event.type === "load" ? "ready" : "error";
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.setAttribute("data-status", targetStatus);
setStatus(targetStatus);
};
ref.current.addEventListener("load", handler);
ref.current.addEventListener("error", handler);
return function () {
var _a, _b, _c;
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("load", handler);
(_b = ref.current) === null || _b === void 0 ? void 0 : _b.removeEventListener("error", handler);
EXTERNAL_USED_COUNT[path] -= 1;
if (EXTERNAL_USED_COUNT[path] === 0 && !(options === null || options === void 0 ? void 0 : options.keepWhenUnused)) {
(_c = ref.current) === null || _c === void 0 ? void 0 : _c.remove();
}
ref.current = undefined;
};
}, [path]);
return status;
};
export default useExternal;