Skip to content

Commit 4bab4da

Browse files
committed
keep main image until blur image is loading
1 parent 6ef147e commit 4bab4da

File tree

1 file changed

+24
-12
lines changed

1 file changed

+24
-12
lines changed

src/components/react/ImageBlurPreloader.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useEffect, useMemo, useState } from 'react';
22

33
import usePrevious from '@/components/react/hooks/usePrevious';
44
import { cn } from '@/utils/styles';
@@ -23,21 +23,31 @@ const ImageBlurPreloader: FC<Props> = ({
2323
className,
2424
divClassName,
2525
}) => {
26-
const [hasLoaded, setHasLoaded] = useState(false);
26+
const [isLoadingMain, setIsLoadingMain] = useState(true);
27+
const [isLoadingBlur, setIsLoadingBlur] = useState(true);
28+
2729
const prevMainAttributes = usePrevious(mainAttributes);
2830

29-
// reset hasLoaded on main image change
31+
const { src, srcSet } = mainAttributes;
32+
const { src: prevSrc, srcSet: prevSrcSet } = prevMainAttributes ?? {};
33+
34+
const isNewImage = useMemo(
35+
() => !(prevSrc === src && prevSrcSet === srcSet),
36+
[src, srcSet, prevSrc, prevSrcSet]
37+
);
38+
39+
// reset isLoading on main image change
3040
useEffect(() => {
31-
// store var in useMemo
32-
if (prevMainAttributes !== mainAttributes) {
33-
setHasLoaded(false);
41+
if (isNewImage) {
42+
setIsLoadingBlur(true);
43+
setIsLoadingMain(true);
3444
}
35-
}, [prevMainAttributes, mainAttributes, setHasLoaded]);
45+
}, [isNewImage, setIsLoadingMain, setIsLoadingBlur]);
3646

3747
// important: main image must be in DOM for onLoad to work
3848
// unmount and display: none will fail
39-
const handleLoad = () => {
40-
setHasLoaded(true); // check if new image
49+
const handleLoadMain = () => {
50+
setIsLoadingMain(false);
4151
onMainLoaded?.();
4252
};
4353

@@ -47,7 +57,7 @@ const ImageBlurPreloader: FC<Props> = ({
4757
height: mainAttributes.height,
4858
};
4959

50-
const hasImage = hasLoaded
60+
const hasImage = isLoadingMain
5161
? mainAttributes.src || mainAttributes.srcSet
5262
: blurAttributes.src || blurAttributes.srcSet;
5363

@@ -59,17 +69,19 @@ const ImageBlurPreloader: FC<Props> = ({
5969
<img
6070
{...blurAttributes}
6171
{...commonAttributes}
72+
onLoad={() => setIsLoadingBlur(false)}
6273
className={cn('object-cover absolute top-0 left-0 size-full', className)}
6374
/>
6475

6576
{/* main image */}
6677
<img
6778
{...mainAttributes}
6879
{...commonAttributes}
69-
onLoad={handleLoad}
80+
onLoad={handleLoadMain}
7081
className={cn(
7182
'object-cover absolute top-0 left-0 size-full',
72-
hasLoaded ? 'opacity-100' : 'opacity-0',
83+
// important: dont hide main image until next blur image is loaded
84+
isLoadingMain && !isLoadingBlur ? 'opacity-0' : 'opacity-100',
7385
className
7486
)}
7587
/>

0 commit comments

Comments
 (0)