background
- Browser's native image not loaded status doesn't look good, I'd like not to use it.
- I am using react.
ideas
- Determine if the image is loaded successfully by
onLoaded
event. - If loaded successfully show the HTMLImageElement, if not show the custom error component while HTMLImageElement is hidden (
visibility: hidden
).
how it looks like
fail
fail with alt on it
success
tips
When load failed, the HTMLImageElement can't be set to
display: none
, the HTMLImageElement needs to be in the document tree. Also the HTMLImageElement should to be invisible and looks like not placed in the web page, so use the grid display to implement this.every time the image is changed, will reload again, so need to set loaded status to false first.
reference
import { cn } from "@/lib/utils";
import { Image } from "lucide-react";
import { useEffect, useState } from "react";
interface ImageProps {
src: string;
iconSize?: number;
className?: string;
alt?: string;
showAlt?: boolean;
}
const BeautyImage = ({
src,
iconSize = 16,
className = "",
alt = "",
showAlt = false,
}: ImageProps) => {
// load successfully or not
const [imageLoaded, setImageLoaded] = useState(false);
/**
* onLoad event
*/
const onImageLoad = () => {
setImageLoaded(true);
};
/**
* everytime the src changes, set load status to fail
*/
useEffect(() => {
setImageLoaded(false);
}, [src]);
return (
<div
className={cn(
"flex flex-col justify-center items-center text-xs text-ttertiary",
className
)}
>
<div
className={cn(
"grid",
imageLoaded
? "grid-rows-[1fr] opacity-100"
: "grid-rows-[0fr] opacity-0"
)}
>
<div className="overflow-hidden">
<img className="rounded-full" src={src} onLoad={onImageLoad} />
</div>
</div>
{/* custom error component */}
{!imageLoaded && (
<div className="flex flex-col items-center justify-center">
<Image size={iconSize} />
{showAlt && alt && <p>{alt}</p>}
</div>
)}
</div>
);
};
Top comments (0)