DEV Community

Dhruv
Dhruv

Posted on

React - handle Image loading error gracefully using custom hook

With the introduction of a hook in react, things around the functions becoming more popular day by day and I really love the idea of "sharable state logic" across the component which is being achieved by the hooks.

Problem statement: How to handle the image throws an error in loading.
The one solution of this would be to directly use onError everywhere in the image. However, you can bring the custom hook here in a very cool way. Let's dive in -

function Image() {
  const [setImg, hasError, retry, imgRef] = useImageError();

  return (
    <img ref={setImg} src="hello.png" alt="hello" />
  );
}

Though the above example serves the purpose. But you what if there is a use cases like - showing something else when there is an error in the image. In that case, there must be use of state which can toggle the component based on error, which I think very tedious process. Instead, the custom hook can be used.

Let's modify the above example a little bit and introduce a hook.

function Image() {
  const [setImg, hasError, retry, imgRef] = useImageError();

  if (hasError) return <div>Error !!!</div>

  return (
    <img ref={setImg} src="hello.png" alt="hello" />
  );
}

The above example shows that there is a hook called useImageError which exposes four keys, setImg - a function which will be used as a callback ref, hasError - a flag which indicates whether there is an error or not, retry - a function which can be used to re-render the image and the last one - which gives the image ref.

const useImageError = () => {
  const [el, setEl] = useState(null); // contains image reference
  const [error, setError] = useState(false); // contains error flag

  const _handleError = () => { setError(true); }  // set error
  const retry = () => { setError(false); } // set error false to img can re-render

  useEffect(() => {
    // use of error event of the image tag
    el?.addEventListener(error, _handleError);

    return () => {
      el?.removeEventListener(error, _handleError);
    }
  }, [el]);

  return [
    setEl, // set the image ref
    error, // error flag
    retry, // a func, which can be used to re-render image
    el // img ref(for special case which requires ref)
  ];
};

So this is the implementation of the useImageError hook which basically listens to the error event on image reference and toggles the error flag based on the error event. The hook takes care of all the state management and event binding which will require tracking the image error.

Of course, you would not do this for a single instance of the image, but yes you can take this if you have multiple occurrences of such cases.

Top comments (0)