lazy-image
efferd-/lazy-imageFreeComponent
Lazy image component.
Install it
npx shadcn@latest add http://efferd.com/r/lazy-image.jsonSource
1"use client";23import { cn } from "@/lib/utils";4import { useInView } from "motion/react";5import React from "react";6import { AspectRatio } from "@/components/ui/aspect-ratio";78type LazyImageProps = {9 alt: string;10 src: string;11 className?: string;12 containerClassName?: string;13 /** URL of the fallback image. default: undefined */14 fallback?: string;15 /** The ratio of the image. */16 ratio: number;17 /** Whether the image should only load when it is in view. default: false */18 inView?: boolean;19};2021export function LazyImage({22 alt,23 src,24 ratio,25 fallback,26 inView = false,27 className,28 containerClassName,29}: LazyImageProps) {30 const ref = React.useRef<HTMLDivElement | null>(null);31 const imgRef = React.useRef<HTMLImageElement | null>(null);32 const isInView = useInView(ref, { once: true });3334 const [imgSrc, setImgSrc] = React.useState<string | undefined>(35 inView ? undefined : src36 );37 const [isLoading, setIsLoading] = React.useState(true);3839 const handleError = () => {40 if (fallback) {41 setImgSrc(fallback);42 }43 setIsLoading(false);44 };4546 const handleLoad = React.useCallback(() => {47 setIsLoading(false);48 }, []);4950 // Load image only when inView51 React.useEffect(() => {52 if (inView && isInView && !imgSrc) {53 setImgSrc(src);54 }55 }, [inView, isInView, src, imgSrc]);5657 // Handle cached images instantly58 React.useEffect(() => {59 if (imgRef.current?.complete) {60 handleLoad();61 }62 }, [handleLoad]);6364 return (65 <AspectRatio66 className={cn(67 "relative size-full overflow-hidden border bg-accent/30",68 containerClassName69 )}70 ratio={ratio}71 ref={ref}72 >73 {imgSrc && (74 // biome-ignore lint/correctness/useImageSize: dynamic image size75 <img76 alt={alt}77 className={cn(78 "size-full object-cover transition-opacity duration-500",79 isLoading ? "opacity-0" : "opacity-100",80 className81 )}82 decoding="async"83 fetchPriority={inView ? "high" : "low"}84 loading="lazy"85 onError={handleError}86 onLoad={handleLoad}87 ref={imgRef}88 role="presentation" // Changed from "img" to "presentation" since it's decorative89 src={imgSrc}90 />91 )}92 </AspectRatio>93 );94}
Files it writes
More from efferd
All 201 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| apple-iconapple-icon | efferd | Components | Free | no deps | |
| auth-dividerauth-divider | efferd | Components | Free | no deps | |
| copy-buttoncopy-button | efferd | Components | Free | no deps | |
| decor-icondecor-icon | efferd | Components | Free | no deps | |
| discord-icondiscord-icon | efferd | Components | Free | no deps | |
| facebook-iconfacebook-icon | efferd | Components | Free | no deps | |
| figma-iconfigma-icon | efferd | Components | Free | no deps | |
| formaterformater | efferd | Components | Free | no deps |
