Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/uidotdev/usehooks into expe…
Browse files Browse the repository at this point in the history
…rimental
  • Loading branch information
benadam11 committed Oct 23, 2023
2 parents 05ceb5e + fa7f8bf commit c980d21
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 75 deletions.
8 changes: 4 additions & 4 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,15 @@ declare module "@uidotdev/usehooks" {
export function useHistoryState<T>(initialPresent?: T): HistoryState<T>;

export function useHover<T extends Element>(): [
React.MutableRefObject<T>,
React.RefCallback<T>,
boolean
];

export function useIdle(ms?: number): boolean;

export function useIntersectionObserver<T extends Element>(
options?: IntersectionObserverInit
): [React.MutableRefObject<T>, IntersectionObserverEntry | null];
): [React.RefCallback<T>, IntersectionObserverEntry | null];

export function useInterval(cb: () => any, ms: number): () => void;

Expand Down Expand Up @@ -242,7 +242,7 @@ declare module "@uidotdev/usehooks" {
export function useMap<T>(initialState?: T): Map<T, any>;

export function useMeasure<T extends Element>(): [
React.MutableRefObject<T>,
React.RefCallback<T>,
{
width: number | null;
height: number | null;
Expand Down Expand Up @@ -287,7 +287,7 @@ declare module "@uidotdev/usehooks" {
options?: {
removeOnUnmount?: boolean;
}
): "idle" | "loading" | "ready" | "error";
): "unknown" | "loading" | "ready" | "error";

export function useSessionStorage<T>(
key: string,
Expand Down
57 changes: 39 additions & 18 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ export function useHover() {

const customRef = React.useCallback(
(node) => {
if (previousNode.current instanceof HTMLElement) {
if (previousNode.current?.nodeType === Node.ELEMENT_NODE) {
previousNode.current.removeEventListener(
"mouseenter",
handleMouseEnter
Expand All @@ -597,7 +597,7 @@ export function useHover() {
);
}

if (node instanceof HTMLElement) {
if (node?.nodeType === Node.ELEMENT_NODE) {
node.addEventListener("mouseenter", handleMouseEnter);
node.addEventListener("mouseleave", handleMouseLeave);
}
Expand Down Expand Up @@ -671,7 +671,7 @@ export function useIntersectionObserver(options = {}) {
previousObserver.current = null;
}

if (node instanceof HTMLElement) {
if (node?.nodeType === Node.ELEMENT_NODE) {
const observer = new IntersectionObserver(
([entry]) => {
setEntry(entry);
Expand Down Expand Up @@ -1003,7 +1003,7 @@ export function useMeasure() {
previousObserver.current = null;
}

if (node instanceof HTMLElement) {
if (node?.nodeType === Node.ELEMENT_NODE) {
const observer = new ResizeObserver(([entry]) => {
if (entry && entry.borderBoxSize) {
const { inlineSize: width, blockSize: height } =
Expand Down Expand Up @@ -1064,7 +1064,7 @@ export function useMouse() {
y: event.pageY,
};

if (ref.current instanceof HTMLElement) {
if (ref.current?.nodeType === Node.ELEMENT_NODE) {
const { left, top } = ref.current.getBoundingClientRect();
const elementPositionX = left + window.scrollX;
const elementPositionY = top + window.scrollY;
Expand Down Expand Up @@ -1386,29 +1386,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
38 changes: 33 additions & 5 deletions usehooks.com/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ const {
ogImage = new URL("/meta/og.jpg", Astro.url),
} = Astro.props;
const pathname = Astro.url.pathname
const url = pathname[pathname.length - 1] === "/"
? new URL(pathname.slice(0, pathname.length -1), Astro.site)
: new URL(Astro.url.pathname, Astro.site)
const pathname = Astro.url.pathname;
const url =
pathname[pathname.length - 1] === "/"
? new URL(pathname.slice(0, pathname.length - 1), Astro.site)
: new URL(Astro.url.pathname, Astro.site);
---

<!DOCTYPE html>
Expand Down Expand Up @@ -90,6 +90,34 @@ const url = pathname[pathname.length - 1] === "/"
data-api="/stats/api/event"
data-domain="usehooks.com"
></script>

<script defer>
!(function (f, b, e, v, n, t, s) {
if (f.fbq) return;
n = f.fbq = function () {
n.callMethod
? n.callMethod.apply(n, arguments)
: n.queue.push(arguments);
};
if (!f._fbq) f._fbq = n;
n.push = n;
n.loaded = !0;
n.version = "2.0";
n.queue = [];
t = b.createElement(e);
t.async = !0;
t.src = v;
s = b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t, s);
})(
window,
document,
"script",
"https://connect.facebook.net/en_US/fbevents.js"
);
fbq("init", "186849069509023");
fbq("track", "PageView");
</script>
</head>
<body>
<slot />
Expand Down
92 changes: 47 additions & 45 deletions usehooks.com/src/sections/Footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,59 @@
---

<footer class="main-footer">
<a href="/" class="logo image">
<img src="/img/logo-useHooks.svg" width="546" height="80" alt="useHooks" />
</a>
<a href="https://ui.dev" class="byline">by ui.dev</a>
<nav>
<a href="https://github.com/uidotdev/usehooks">Fork on GitHub</a>
<a href="https://bytes.dev">JavaScript Newsletter</a>
<a href="https://react.gg">Learn React</a>
</nav>
<a href="/" class="logo image">
<img src="/img/logo-useHooks.svg" width="546" height="80" alt="useHooks" />
</a>
<a href="https://ui.dev" class="byline">by ui.dev</a>
<nav>
<a href="https://github.com/uidotdev/usehooks">View the Repo</a>
<a href="https://bytes.dev">JavaScript Newsletter</a>
<a href="https://reactnewsletter.com">React Newsletter</a>
<a href="https://react.gg">Learn React</a>
<a href="https://query.gg">Learn React Query</a>
</nav>
</footer>

<style>
.main-footer {
width: 100%;
margin-top: 4rem;
padding: var(--body-padding);
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
border-radius: .5rem;
border: var(--border-dark);
font-size: var(--font-sm);
}
.main-footer {
width: 100%;
margin-top: 4rem;
padding: var(--body-padding);
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
border-radius: 0.5rem;
border: var(--border-dark);
font-size: var(--font-sm);
}

nav {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1rem 2rem;
text-align: center;
}
nav {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1rem 2rem;
text-align: center;
}

.logo {
width: 180px;
}
.logo {
width: 180px;
}

.byline {
margin-top: -.5rem;
padding: .3em .5em;
display: inline-block;
border-radius: .3em;
background-color: var(--charcoal);
}
.byline {
margin-top: -0.5rem;
padding: 0.3em 0.5em;
display: inline-block;
border-radius: 0.3em;
background-color: var(--charcoal);
}

.byline:hover {
background-color: var(--yellow);
color: var(--charcoal);
}
.byline:hover {
background-color: var(--yellow);
color: var(--charcoal);
}

nav a:hover {
text-decoration: underline;
}
nav a:hover {
text-decoration: underline;
}
</style>

0 comments on commit c980d21

Please sign in to comment.