DEV Community

Jen C.
Jen C.

Posted on

How to Perform Actions After an Image Loads in React: Using the onLoad Event or the complete Property

The load event triggered by an HTML element does not bubble up to the window object by default. Therefore, when an image is loaded using an img HTML element, if you need to notify the window object, you must manually dispatch the event to it.

An example:

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
    <img id="image" src="https://placehold.co/100x100" alt="Placeholder Image" />
    <script src="src/script.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

JS

document.getElementById('image').addEventListener('load', function() {
  console.log('Image load event');
  window.dispatchEvent(new Event('load'));  // Manually dispatch load event to window
});

window.addEventListener('load', function() {
  console.log('Window load event');
});
Enter fullscreen mode Exit fullscreen mode

Console output: the second log 'Window Load Event' is triggered by calling dispatchEvent

Image load event
Window load event
Window load event
Enter fullscreen mode Exit fullscreen mode

Examples of Updating Text Based on Image Loading Status in React

Example 1: Using HTML 'complete' Property

Simulating an API call to fetch an image URL and passing it to the Banner component triggers a re-render when imgUrl changes, allowing the correct value of completed to be captured at the second render stage.

import { useRef , useState , useEffect } from "react";

export default function App() {
    const [imgUrl, setImgUrl] = useState("");
    useEffect(() => {
        // simulate calling API to get image url
        const loadImage = () => {
            setTimeout(() => {
                setImgUrl("https://placehold.co/200x100")
          }, 1500);
        }
      loadImage();
    }, []);
    return <Banner imgUrl={imgUrl} />
}

function Banner({ imgUrl }) {
    const ref = useRef(null);
    // this works when the imgUrl changes, triggering a re-render. Otherwise, the value of completed will always be false
   const completed = Boolean(ref.current?.complete);
    return (
        <div>
            <img ref={ref} src={imgUrl}
                onLoad={() => console.log("loaded")}
                onError={() => console.log("error")}/>
            <p>{completed ? "Image loaded" : "Image is not loaded"}</p>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Example 2: Using onLoad Event

Update the component state in the onLoad event callback

function StaticBanner() {
    const [loaded, setLloaded] = useState(false);
    return (
        <div>
            <img src="https://placehold.co/100x100"
                onLoad={() => {
                    console.log("StaticBanner img loaded");
                    setLloaded(true);
                }}
                onError={() => console.log("StaticBanner img error")}/>
            <p>{loaded ? "Image loaded" : "Image is not loaded"}</p>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

What if a Banner lives in the DOM and does not unmount, but the img url that is passed into the component as a prop that changes constantly?

To be continued...

Top comments (0)