Skip to content

Commit

Permalink
Re-implement useScript
Browse files Browse the repository at this point in the history
  • Loading branch information
tylermcginnis committed Oct 23, 2023
1 parent 0a4eb07 commit d057a9b
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 17 deletions.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ declare module "@uidotdev/usehooks" {
options?: {
removeOnUnmount?: boolean;
}
): "idle" | "loading" | "ready" | "error";
): "unknown" | "loading" | "ready" | "error";

export function useSessionStorage<T>(
key: string,
Expand Down
47 changes: 34 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1101,29 +1101,50 @@ export function useScript(src, options = {}) {
React.useEffect(() => {
let script = document.querySelector(`script[src="${src}"]`);

const domStatus = script?.getAttribute("data-status");
if (domStatus) {
setStatus(domStatus);
return;
}

if (script === null) {
script = document.createElement("script");
script.src = src;
script.async = true;
script.setAttribute("data-status", "loading");
document.body.appendChild(script);
}

const handleScriptLoad = () => setStatus("ready");
const handleScriptError = () => setStatus("error");
const handleScriptLoad = () => {
script.setAttribute("data-status", "ready");
setStatus("ready");
removeEventListeners();
};

script.addEventListener("load", handleScriptLoad);
script.addEventListener("error", handleScriptError);
const handleScriptError = () => {
script.setAttribute("data-status", "error");
setStatus("error");
removeEventListeners();
};

const removeOnUnmount = optionsRef.current.removeOnUnmount;
const removeEventListeners = () => {
script.removeEventListener("load", handleScriptLoad);
script.removeEventListener("error", handleScriptError);
};

return () => {
script.removeEventListener("load", handleScriptLoad);
script.removeEventListener("error", handleScriptError);
script.addEventListener("load", handleScriptLoad);
script.addEventListener("error", handleScriptError);

if (removeOnUnmount === true) {
script.remove();
}
};
const removeOnUnmount = optionsRef.current.removeOnUnmount;

return () => {
if (removeOnUnmount === true) {
script.remove();
removeEventListeners();
}
};
} else {
setStatus("unknown");
}
}, [src]);

return status;
Expand Down
5 changes: 2 additions & 3 deletions usehooks.com/src/content/hooks/useScript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import StaticCodeContainer from "../../components/StaticCodeContainer.astro";
scripts into a React component. It manages the loading and status of the
script, allowing you to conditionally render components or perform actions
based on whether the script has been successfully loaded or encountered an
error. The hook keeps track of the script’s status, such as "loading,"
"ready," or "error," and provides this status as a return value. Additionally,
error. The hook keeps track of the script’s status and provides this status as a return value. Additionally,
it offers options to remove the script when the component is unmounted,
ensuring proper cleanup.
</HookDescription>
Expand All @@ -38,7 +37,7 @@ import StaticCodeContainer from "../../components/StaticCodeContainer.astro";
<div class="table-container">
| Name | Type | Description |
| ------ | ------ | ----------- |
| status | string | This represents the status of the script load. Possible values are: `loading`, `ready`, and `error`. |
| status | string | This represents the status of the script load, `loading`, `ready`, `error`, or `unknown`. An `unknown` script is one that previously exists in the document, but was not added via `useScript`. |
</div>
</div>

Expand Down

0 comments on commit d057a9b

Please sign in to comment.