A Better Way to Render Images in React
2 min readDec 10, 2022
What I used to do
Render an image with img element and if src is null or undefined, render a fallback image.
import { FC } from "react";
type ImageProps = {
src: string;
alt: string;
};
const Image: FC<ImageProps> = ({src, alt}) => {
return <img alt={alt} src={src || "fallback.jpg"}/>;
}
But what if src is malformed or protected that cannot be accessed through the App?
This method fails and renders an empty image with the given alt.
What happens when an image fails
Whenever an image fails to load, an onError event is triggered, we can use this event to update src to a fallback image.
Updates for the fix
Instead of directly adding an optional condition of the fallback image, we can add an onError event handler to do the same.
useImage Hook
import { SyntheticEvent, useEffect, useState } from "react";
import { ImageProps } from "./Image";
type ImagePropsGetter = () => ImageProps & {
onError: (e: SyntheticEvent<HTMLImageElement>) => void;
};
const useImage = ({
src: srcFromProps,
alt
}: ImageProps): { getImageProps: ImagePropsGetter } => {
const [src, setSrc] = useState(srcFromProps);
const onError = () => {
setSrc("fallback.jpg");
};
useEffect(() => {
setSrc(srcFromProps);
}, [srcFromProps]);
const getImageProps: ImagePropsGetter = () => {
return { src, alt, onError };
};
return { getImageProps };
};
export default useImage;
Image Component
import { FC } from "react";
import useImage from "./useImage";
export type ImageProps = {
src: string;
alt: string;
};
const Image: FC<ImageProps> = (props) => {
const { getImageProps } = useImage(props);
return <img {...getImageProps()} />;
};
export default Image;
No More Empty Images!
Thanks