How to Smoothly Render Images in React App?
Tags: react, ux, webdev, css
Published: 2020-03-09 05:00:23

Improve your web apps UX by enhancing image render with React's `onLoad` event and simple SCSS.

> This article is cross-posted on [Codebrahma](https://codebrahma.com/how-to-smoothly-render-images-in-react-app/) and [Medium](https://medium.com/@krrish96/how-to-smoothly-render-images-in-react-app-3110b9de15c9?source=friends_link&sk=3f6f6d91bd36b71b677788be61a96ae9)

Let's cut to the chase. The GIF below shows what we are going to achieve by the end of this post.

![Default Image Rendering vs Smooth Image Rendering using render-smooth-image-react](https://dev-to-uploads.s3.amazonaws.com/i/1svw6ve8lqh6eax9cgcj.gif)

<figcaption>Default Image Rendering vs Smooth Image Rendering using <a href="https://www.npmjs.com/package/render-smooth-image-react">render-smooth-image-react</a></figcaption>

Here is the Completed Component - `RenderSmoothImage`.

{% gist https://gist.github.com/KRRISH96/48b4200bc73f1071da804911c05ea373 %}
<figcaption>Final Code — RenderSmoothImage — React Component</figcaption>

I have published this as an `npm` package [render-smooth-image-react](https://www.npmjs.com/package/render-smooth-image-react). The source code is available on [GitHub](https://github.com/KRRISH96/render-smooth-image-react).

<hr></hr>

## **Little Back Story**

I recently started working on a media-heavy app. Everything was cool until I noticed a bunch of images rendering poorly. Which looked something like this.

![Example: Poor image rendering (printing)](https://dev-to-uploads.s3.amazonaws.com/i/4jffgawbo06trncm47bs.gif)
<figcaption>Example: Poor image rendering (printing)</figcaption>

For a moment I thought, “Did I end up building a 🖨 *printer simulator app*?”

Overall customer satisfaction will take a hit with such poor loading UX (even if the rest of the app is great). This is especially true for media-heavy apps.

Alright, Let’s see what we can do to fix this.

<hr></hr>

## **Load and Fire** 🔫

> *Let the browser download the image and render it.*

The perfect moment to render an image is after downloading completely. Till then we just show a loader/placeholder and hide the image.

We can achieve this by using React’s [onLoad](https://reactjs.org/docs/events.html#image-events) event on the image tag. You can read more about [React.js](https://reactjs.org/)  events [here](https://reactjs.org/docs/events.html).

```html
  <img onLoad={'callbackAfterImageIsDownloaded'} />
```


## **Code it**

We will create a functional component and use hooks to maintain a couple of states. If you are new to React Hooks, You can learn more [here](https://reactjs.org/docs/hooks-intro.html).

```jsx
  // RenderSmoothImage.jsx

  function RenderSmoothImage({src, alt}) {
    const [imageLoaded, setImageLoaded]=React.useState(false);

    return (
      <div className="smooth-image-wrapper">
        <img
          src={src}
          alt={alt}
          className={`smooth-image image-${
            imageLoaded ? 'visible' :  'hidden'
          }`}
          onLoad={()=> setImageLoaded(true)}}
        />
        {!imageLoaded && (
          <div className="smooth-preloader">
            <span className="loader" />
          </div>
        )}
      </div>
    )
  }
```
```css
/** styles.css */

  .smooth-image {
    transition: opacity 1s; 
  }
  .image-visible {opacity: 1}
  .image-hidden {opacity: 0}
```

Here, we maintain a state `imageLoaded` defaults to `false`. Which will then be set to `true`, once the image is downloaded. We use the `onLoad` event to trigger this.

Then we use `imageLoaded` state to conditionally add classes to the `img` tag, `image-visible` vs `image-hidden`. We can add transitions/animations to make it smoother. Please refer to the linked Gist at the top for complete styles.

That’s it! No more printer simulators on the page.

<hr></hr>

## **What if Image Download Fails / Invalid Src?**


![Image for alternate text with image tag](https://dev-to-uploads.s3.amazonaws.com/i/ett00jm3yvkn4ci7ko6w.png)

<figcaption>Image for alternate text with image tag</figcaption>

By using the `alt` attribute we can show alternate text for the image. However, the default icon and styling isn’t too great. To fix this we can display custom `alt` text.

```jsx
  // RenderSmoothImage.jsx

  function RenderSmoothImage({src, alt}) {
    .....
    const [isValidSrc, setIsValidSrc] = React.useState(!!src);

    return (
      <div className="smooth-image-wrapper">
        {isValidSrc ? (
          <img
            ....
            onError={() => setIsValidSrc(false)}
          />
        ) : (
          <div className="smooth-no-image">{alt}</div>
        )}
        {isValidSrc && !imageLoaded && (
          <div className="smooth-preloader">
            <span className="loader" />
          </div>
        )}
      </div>
    )
  }
```
```css
    /** styles.css */
    ......
    .smooth-no-image {
      background-image: linear-gradient(90deg,#ccc,#999,#ccc);
      color: #fff;
    }
```

There you go,

![Customized Alternate Text for Image](https://dev-to-uploads.s3.amazonaws.com/i/dr3ugd8u7veu2d1vg57l.png)

<figcaption>Customized Alternate Text for Image</figcaption>

You can style the Alternative text any way you want.

I made things easy for you and published a light-weight npm package [render-smooth-image-react](https://www.npmjs.com/package/render-smooth-image-react).


Thank you for reading this post, This is [Sai Krishna Prasad](https://www.linkedin.com/in/kskp1996), a self-taught and passionate web developer. Signing off Bubye….. until next time.