useLazyLoading: start loading when near viewport
## Issue #6332 <Thumbnail lazy-loader is too slow || Use browser-level lazy-loading> ## Change Switch from "threshold-based check" to "viewport distance comparison" using the `rootMargin` parameter. The root is the viewport. This change makes it closer to the native `loading="lazy"` behavior, where it starts to load when approaching the viewport. Chrome I believe uses 3000px distance -- I think 500px is a good compromise for now. Can adjust further. ## Future - We are currently creating N instances of IntersectionObserver. - https://developers.google.com/web/updates/2016/04/intersectionobserver - "If you need to observe multiple elements, it is both possible and advised to observe multiple elements using the same IntersectionObserver instance by calling observe() multiple times." This would probably need a refactor to make ClaimList (or something higher) own the IntersectionObserver.
This commit is contained in:
parent
59a8b9d663
commit
f7cf21b661
1 changed files with 14 additions and 4 deletions
|
@ -5,15 +5,24 @@ import React, { useEffect } from 'react';
|
||||||
/**
|
/**
|
||||||
* Helper React hook for lazy loading images
|
* Helper React hook for lazy loading images
|
||||||
* @param elementRef - A React useRef instance to the element to lazy load.
|
* @param elementRef - A React useRef instance to the element to lazy load.
|
||||||
* @param {Number} [threshold=0.5] - The percent visible in order for loading to begin.
|
* @param yOffsetPx - Number of pixels from the viewport to start loading.
|
||||||
* @param {Array<>} [deps=[]] - The dependencies this lazy-load is reliant on.
|
* @param {Array<>} [deps=[]] - The dependencies this lazy-load is reliant on.
|
||||||
*/
|
*/
|
||||||
export default function useLazyLoading(
|
export default function useLazyLoading(
|
||||||
elementRef: { current: ?ElementRef<any> },
|
elementRef: { current: ?ElementRef<any> },
|
||||||
threshold: number = 0.25,
|
yOffsetPx: number = 500,
|
||||||
deps: Array<any> = []
|
deps: Array<any> = []
|
||||||
) {
|
) {
|
||||||
const [srcLoaded, setSrcLoaded] = React.useState(false);
|
const [srcLoaded, setSrcLoaded] = React.useState(false);
|
||||||
|
const threshold = 0.01;
|
||||||
|
|
||||||
|
function calcRootMargin(value) {
|
||||||
|
const devicePixelRatio = window.devicePixelRatio || 1.0;
|
||||||
|
if (devicePixelRatio < 1.0) {
|
||||||
|
return Math.ceil(value / devicePixelRatio);
|
||||||
|
}
|
||||||
|
return Math.ceil(value * devicePixelRatio);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!elementRef.current) {
|
if (!elementRef.current) {
|
||||||
|
@ -45,11 +54,12 @@ export default function useLazyLoading(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
root: null,
|
root: null,
|
||||||
rootMargin: '0px',
|
rootMargin: `0px 0px ${calcRootMargin(yOffsetPx)}px 0px`,
|
||||||
threshold,
|
threshold: [threshold],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// $FlowFixMe
|
||||||
lazyLoadingObserver.observe(elementRef.current);
|
lazyLoadingObserver.observe(elementRef.current);
|
||||||
}, deps);
|
}, deps);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue