Use lazy loading (react-intersection-observer) for image loading

This commit is contained in:
Kendall Garner 2025-07-07 20:11:32 -07:00
parent e00aeb2b67
commit 49bb42a298
No known key found for this signature in database
GPG key ID: 9355F387FE765C94
3 changed files with 54 additions and 26 deletions

View file

@ -112,6 +112,7 @@
"react-i18next": "^11.18.6",
"react-icons": "^5.5.0",
"react-image": "^4.1.0",
"react-intersection-observer": "^9.16.0",
"react-loading-skeleton": "^3.5.0",
"react-player": "^2.11.0",
"react-router": "^6.16.0",

18
pnpm-lock.yaml generated
View file

@ -182,6 +182,9 @@ importers:
react-image:
specifier: ^4.1.0
version: 4.1.0(@babel/runtime@7.27.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-intersection-observer:
specifier: ^9.16.0
version: 9.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-loading-skeleton:
specifier: ^3.5.0
version: 3.5.0(react@19.1.0)
@ -3655,6 +3658,15 @@ packages:
react: '>=16.8'
react-dom: '>=16.8'
react-intersection-observer@9.16.0:
resolution: {integrity: sha512-w9nJSEp+DrW9KmQmeWHQyfaP6b03v+TdXynaoA964Wxt7mdR3An11z4NNCQgL4gKSK7y1ver2Fq+JKH6CWEzUA==}
peerDependencies:
react: ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta:
react-dom:
optional: true
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@ -8458,6 +8470,12 @@ snapshots:
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-intersection-observer@9.16.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
react: 19.1.0
optionalDependencies:
react-dom: 19.1.0(react@19.1.0)
react-is@16.13.1: {}
react-loading-skeleton@3.5.0(react@19.1.0):

View file

@ -2,6 +2,7 @@ import clsx from 'clsx';
import { motion, MotionConfigProps } from 'motion/react';
import { type ImgHTMLAttributes } from 'react';
import { Img } from 'react-image';
import { InView } from 'react-intersection-observer';
import styles from './image.module.css';
@ -44,33 +45,41 @@ export function Image({
}: ImageProps) {
if (src) {
return (
<Img
className={clsx(styles.image, className)}
container={(children) => (
<ImageContainer
className={containerClassName}
enableAnimation={enableAnimation}
{...imageContainerProps}
>
{children}
</ImageContainer>
<InView>
{({ inView, ref }) => (
<div ref={ref}>
{inView && (
<Img
className={clsx(styles.image, className)}
container={(children) => (
<ImageContainer
className={containerClassName}
enableAnimation={enableAnimation}
{...imageContainerProps}
>
{children}
</ImageContainer>
)}
loader={
includeLoader ? (
<ImageContainer className={containerClassName}>
<ImageLoader className={className} />
</ImageContainer>
) : null
}
src={src}
unloader={
includeUnloader ? (
<ImageContainer className={containerClassName}>
<ImageUnloader className={className} />
</ImageContainer>
) : null
}
/>
)}
</div>
)}
loader={
includeLoader ? (
<ImageContainer className={containerClassName}>
<ImageLoader className={className} />
</ImageContainer>
) : null
}
src={src}
unloader={
includeUnloader ? (
<ImageContainer className={containerClassName}>
<ImageUnloader className={className} />
</ImageContainer>
) : null
}
/>
</InView>
);
}