DEV Community

Cover image for 【Next.js, React.js】Making Image with Loading component.
Kota Ito
Kota Ito

Posted on

【Next.js, React.js】Making Image with Loading component.

In this post, I'll share a simple technique to create a reusable image component in Next.js that displays a loading indicator until the image has fully loaded. This is achieved using the onLoad event handler provided by Next.js's Image component.

ImageWithLoading component


import Image from 'next/image';
import React from 'react';
import cn from 'classnames';
import Loading from '@/components/elements/message/Loading';

type ImageProps = {
  id: string;
  url: string;
  alt: string;
};

const ImageWithLoading: React.FC<ImageProps> = ({ url, alt }) => {
  const [imageLoaded, setImageLoaded] = React.useState<boolean>(false);

  return (
    <>
      {!imageLoaded && <Loading size="large" />}
      <Image
        src={url}
        alt={alt}
        fill={true}
        style={{ objectFit: 'cover' }}
        className={cn('rounded-md', { 'opacity-0': !imageLoaded })}
        onLoad={() => setImageLoaded(true)}
      />
    </>
  );
};

export default ImageWithLoading;
Enter fullscreen mode Exit fullscreen mode

In this component:

  • The imageLoaded state is initially set to false, indicating that the image has not yet loaded.

  • The Loading component is displayed while imageLoaded is false.

  • The Image component's className uses the classnames (imported as cn) library to conditionally apply the 'opacity-0' class when imageLoaded is false, making the image transparent.

  • The onLoad event handler sets imageLoaded to true once the image has finished loading, which removes the 'opacity-0' class and hides the Loading component.

Using the classnames library instead of template literals for conditional class names enhances the reusability of the component. It provides a standardized and efficient way to handle dynamic class names, improving code readability and maintainability.

Use case

 <div htmlFor={piece.id} 
className="flex relative h-[200px] w-[150px] bg-white rounded-md"> 
   <ImageWithLoading id={piece.id} url={piece.imageUrl} alt={piece.title} />
</div>
Enter fullscreen mode Exit fullscreen mode

Note:
When using the fill prop in Next.js Image, it's important to note that the image will be positioned relative to the nearest ancestor element with a position: relative; style, or it will be positioned relative to the root of the document if no such ancestor is found. Therefore, to ensure that the image is positioned and sized correctly, you should add the relative class to a parent element or suitable ancestor element.

Photo credit:
from Unsplash
by Mike van den Bos

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay