Skip to content

Instantly share code, notes, and snippets.

@rmarscher
Last active February 19, 2025 22:06
Show Gist options
  • Save rmarscher/20c3c18cfb7e5d24f284943dfe48a9dc to your computer and use it in GitHub Desktop.
Save rmarscher/20c3c18cfb7e5d24f284943dfe48a9dc to your computer and use it in GitHub Desktop.
Waku useHashScroll hook
import { useEffect, useRef } from "react";
import { useRouter_UNSTABLE as useRouter } from "waku/router/client";
function scrollIntoView(hash: string) {
const elementId = hash.slice(1);
const element = document.getElementById(elementId);
if (!element) {
return false;
}
element.scrollIntoView({ behavior: "auto", block: "start" });
return true;
}
export function useHashScroll() {
const hashRef = useRef("");
const router = useRouter();
const path = router.path;
hashRef.current = router.hash;
useEffect(() => {
path; // mark path as an effect dependency
let cancel = false;
const timeoutRef = { current: undefined };
if (hashRef.current) {
if (!scrollIntoView(hashRef.current)) {
let attempt = 1;
const retries = 4;
const tryScroll = () => {
if (cancel) return;
const res = scrollIntoView(hashRef.current);
if (res) {
timeoutRef.current = undefined;
return;
}
if (attempt < retries) {
attempt++;
timeoutRef.current = window.setTimeout(
tryScroll,
2 ** attempt * 200,
);
}
};
timeoutRef.current = window.setTimeout(tryScroll, 2 ** attempt * 200);
}
}
return () => {
cancel = true;
if (timeoutRef.current) window.clearTimeout(timeoutRef.current);
};
}, [path]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment