DEV Community

Filipe Névola
Filipe Névola

Posted on

11

React Image component resilient to flaky connections

I would like to explain here how I include images in my React projects.

It's very common to use the img tag directly everywhere like this <img src="my-image.png" /> but as this is not a React component we can't apply some layer on it then I prefer to have an Image component in my apps.

In this Image component one case that I usually handle is when the image fails to load, this can happen when the user internet connection is flaky or even if the image is not available anymore, maybe the owner of the image just deleted it.

By default, the browser will display a broken image icon or something bad for the user and we don't want that. So we can use the onError property of img to trigger a state change then we can provide a different image URL that we can trust. Check the Image component code.

import React, { useState } from 'react';
export const Image = ({ src, srcOnError, ...rest }) => {
const [srcImg, setSrcImg] = useState(null);
const onError = () => {
setSrcImg(srcOnError);
};
const cachedSrc = transformUrlForCaching(src);
if (!srcOnError) {
return <img src={src} {...rest} />;
}
if (srcImg) {
return <img src={srcImg} {...rest} />;
}
return <img src={src} onError={onError} {...rest} />;
};
view raw Image.js hosted with ❤ by GitHub

Then when the user's connection fails the browser will not show a broken image icon if we provide a better fallback when using this Image component, for instance, in a PersonImage component that displays the user profile picture in our app.

import React from 'react';
import { Image } from './Image';
const DEFAULT_PROFILE_IMAGE_URL = '/images/people-profile-default.png';
export const PersonImage = ({ profileImageUrl, ...rest }) => (
<Image src={profileImageUrl} srcOnError={DEFAULT_PROFILE_IMAGE_URL} {...rest} />
);
view raw PersonImage.js hosted with ❤ by GitHub

I believe you are thinking: how the browser is going to load the fallback image anyway if the connection is failing? Well, we can add in our HTML head section a preload link to load our fallback image in advance:

<head>
<link rel="preload" href="/images/people-profile-default.png" as="fetch">
</head>
view raw head.html hosted with ❤ by GitHub

That is it, simple and straightforward. Are you doing something like this in our React apps? Did you know about onError property already? Leave a comment 😉

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (1)

Collapse
 
varsenyan profile image
Vlad

Hah) thank you, it helps me)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay