@@ -8,6 +8,7 @@ const baseClass = 'thumbnail'
8
8
import type { SanitizedCollectionConfig } from 'payload'
9
9
10
10
import { File } from '../../graphics/File/index.js'
11
+ import { useIntersect } from '../../hooks/useIntersect.js'
11
12
import { ShimmerEffect } from '../ShimmerEffect/index.js'
12
13
13
14
export type ThumbnailProps = {
@@ -29,7 +30,15 @@ export const Thumbnail = (props: ThumbnailProps) => {
29
30
const [ src , setSrc ] = React . useState < null | string > (
30
31
fileSrc ? `${ fileSrc } ${ imageCacheTag ? `?${ imageCacheTag } ` : '' } ` : null ,
31
32
)
33
+ const [ intersectionRef , entry ] = useIntersect ( )
34
+ const [ hasPreloaded , setHasPreloaded ] = React . useState ( false )
35
+
32
36
React . useEffect ( ( ) => {
37
+ if ( ! entry ?. isIntersecting || hasPreloaded ) {
38
+ return
39
+ }
40
+ setHasPreloaded ( true )
41
+
33
42
if ( ! fileSrc ) {
34
43
setFileExists ( false )
35
44
return
@@ -58,12 +67,12 @@ export const Thumbnail = (props: ThumbnailProps) => {
58
67
img . src = fileSrc
59
68
img . onload = ( ) => setFileExists ( true )
60
69
img . onerror = ( ) => setFileExists ( false )
61
- } , [ fileSrc , fileType , imageCacheTag ] )
70
+ } , [ fileSrc , fileType , imageCacheTag , entry , hasPreloaded ] )
62
71
63
72
const alt = props . alt || ( filename as string )
64
73
65
74
return (
66
- < div className = { classNames } >
75
+ < div className = { classNames } ref = { intersectionRef } >
67
76
{ fileExists === undefined && < ShimmerEffect height = "100%" /> }
68
77
{ fileExists && < img alt = { alt } src = { src } /> }
69
78
{ fileExists === false && < File /> }
0 commit comments