Created
March 26, 2022 14:59
-
-
Save LironHazan/9efbc3d3fd205eeaba794e1654c15747 to your computer and use it in GitHub Desktop.
A react utility component for Lazy-loading of content as a page is scrolled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useRef, useEffect } from 'react'; | |
import RectContentLoader from './RectContentLoader'; | |
export interface VirtRenderingProps { | |
placeholderHeight?: number; // the height of the rendered item | |
root?: HTMLElement | null; // If the root is null, then the bounds of the actual document viewport are used. | |
children: React.ReactNode; | |
} | |
/** | |
* A utility component for Lazy-loading of content as a page is scrolled. | |
* @param placeholderHeight | |
* @param root | |
* @param children | |
* @constructor | |
*/ | |
const LazyLoadChildren = ({ | |
placeholderHeight = 40, | |
root = null, | |
children, | |
}: VirtRenderingProps) => { | |
const [isVisible, setIsVisible] = useState<boolean>(false); | |
const intersectionRef = useRef<HTMLDivElement>(null); | |
const _placeholderHeight = | |
intersectionRef?.current?.offsetHeight ?? placeholderHeight; | |
useEffect(() => { | |
let observer: IntersectionObserver; | |
const currentIntersectionRef = intersectionRef.current; | |
if (currentIntersectionRef) { | |
observer = new IntersectionObserver( | |
(entries) => { | |
if (window?.requestIdleCallback) { | |
window.requestIdleCallback( | |
() => setIsVisible(entries[0].isIntersecting), | |
{ | |
timeout: 500, | |
} | |
); | |
} else { | |
setIsVisible(entries[0].isIntersecting); | |
} | |
}, | |
{ root } | |
); | |
observer.observe(currentIntersectionRef); | |
return () => | |
currentIntersectionRef && observer.unobserve(currentIntersectionRef); | |
} | |
return () => | |
currentIntersectionRef && observer.unobserve(currentIntersectionRef); | |
}, [intersectionRef]); | |
return ( | |
<div ref={intersectionRef}> | |
{isVisible ? ( | |
<>{children}</> | |
) : ( | |
<RectContentLoader | |
placeholderHeight={_placeholderHeight || placeholderHeight} | |
/> | |
)} | |
</div> | |
); | |
}; | |
export default LazyLoadChildren; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment