DEV Community

Diego (Relatable Code)
Diego (Relatable Code)

Posted on • Updated on

How to share dynamically generated images in React

I have been developing a pokémon related app where you can track encounters. Throughout the process I also added a way to generate a summary image of the run:

Image description

Generating the image was easy enough, but typically most users would want to share that image directly to a social media site. In comes the Web Share API! With this it can natively check for methods from the OS to share the site, so direct integration with Facebook, Twitter, Reddit, etc is unnecessary.

DISCLAIMER: For the time being this API has limited compatibility across some operating systems and browsers. Check out https://caniuse.com/?search=navigator.share for the current state.

The Requirements

  • Share button
  • Dynamically generate an image from the HTML
  • When clicking the share button share the image to a variety of different options

The Setup

Before anything else, to dynamically generate the image a third-party library is necessary. In this tutorial, I will be using html-to-image. Cool! Now, let’s go ahead and start setting up the share button.

<div>
   <h1>Dynamically generate and share images</h1>
   <button>Share</button>
   <div>
       // ...Dynamically generated content
   </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Simple enough. In order to extract the content let’s set up html-to-image. First, we need to hook up the div that’s going to contain the dynamic content with a ref using the useRef hook from React.

const imageRef = useRef(null);

<div>
   <h1>Dynamically generate and share images</h1>
   <button>Share</button>
   <div ref={imageRef}>
       // ...Dynamically generated content
   </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Create and share the image

html-to-image provides us with a function to directly take out the HTML element and create an image: toBlob. Here we create the function:

const handleShare = async () => {
    const newFile = await toBlob(imageRef.current);
    const data = {
      files: [
        new File([newFile], 'image.png', {
          type: newFile.type,
        }),
      ],
      title: 'Image',
      text: 'image',
    };
}
Enter fullscreen mode Exit fullscreen mode

Also, we must format the result to correctly be able to share. We can do this by making the image into a Blob by extracting the current value from the Ref as well as setting a title and text.

const handleShare = async () => {
    const newFile = await toBlob(imageRef.current);
    const data = {
      files: [
        new File([newFile], 'image.png', {
          type: newFile.type,
        }),
      ],
      title: 'Image',
      text: 'image',
    };

    try {
      await navigator.share(data);
   } catch (err) {
     console.error(err);
   }
}
Enter fullscreen mode Exit fullscreen mode

Sharing the image is as simple as sharing the constructed data. This will automatically bring up a list of options available. But, wait! Earlier I mentioned compatibility issues, for that reason I added a try and catch, but we can take this a step further, the API also provides us a function to check if the data can be shared at all: navigator.canShare.

  try {
      if (!navigator.canShare(data)) {
        console.error("Can't share");
      }
      await navigator.share(data);
    } catch (err) {
      console.error(err);
    }
Enter fullscreen mode Exit fullscreen mode

Check out the end result with the function hooked up to the button:

How the share shows up on mobile:

Image description

Let me know how you used the Web Share API in the comments below!

Top comments (1)

Collapse
 
vikasbairwa profile image
vikasbairwa

will it work for sharing image by the user on Instagram LinkedIn and twitter.
the website i am working on has phone centric ui and once the user clicks on share image icon i needs to share image on insta story and the other platforms.