54 lines
1.2 KiB
TypeScript
54 lines
1.2 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import { useFetcher } from '@remix-run/react';
|
|
|
|
export function usePrefetchOnHover(href: string) {
|
|
const fetcher = useFetcher();
|
|
const prefetched = useRef(false);
|
|
|
|
const prefetch = () => {
|
|
if (!prefetched.current && href) {
|
|
prefetched.current = true;
|
|
fetcher.load(href);
|
|
}
|
|
};
|
|
|
|
return {
|
|
onMouseEnter: prefetch,
|
|
onFocus: prefetch,
|
|
onTouchStart: prefetch,
|
|
};
|
|
}
|
|
|
|
export function usePrefetchOnVisible(href: string, options?: IntersectionObserverInit) {
|
|
const fetcher = useFetcher();
|
|
const ref = useRef<HTMLElement>(null);
|
|
const prefetched = useRef(false);
|
|
|
|
useEffect(() => {
|
|
if (!href || !ref.current || prefetched.current) return;
|
|
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting && !prefetched.current) {
|
|
prefetched.current = true;
|
|
fetcher.load(href);
|
|
observer.disconnect();
|
|
}
|
|
});
|
|
},
|
|
{
|
|
rootMargin: '50px',
|
|
...options,
|
|
}
|
|
);
|
|
|
|
observer.observe(ref.current);
|
|
|
|
return () => {
|
|
observer.disconnect();
|
|
};
|
|
}, [href, fetcher, options]);
|
|
|
|
return ref;
|
|
} |