Share content natively with the Web Share API
Tags: javascript, tutorial, mobile, webdev
Published: 2020-07-25 09:42:25

Today I'm going to explain how to share content natively using the [Web Share API](https://www.w3.org/TR/web-share/).

## Introduction

I first found out about this API when trying to figure out how to allow users of [an application I was developing](https://tisn.app/) to share content with other applications. I didn't want to use external libraries or have to manually implement methods for every application I wanted to support (among other things because I wanted to support them all 😛) and was so glad when I finally found this API and saw that it was exactly what I was looking for! As I think not so many people know about the API yet, I'll try to explain how it works hoping that it will help anyone in the same situation I found myself in.

Before starting, it's worth noting that [the API isn't supported by many of the major browsers yet](https://caniuse.com/#feat=web-share). However, it will work for pretty much any user browsing your web application from their phones, which is where it is more necessary in my opinion. As such, a fallback mechanism will have to be implemented for when the user is using a browser that doesn't support the API.

## Context

In this tutorial I'll walk you through my own implementation of the API, which was on a [React](https://reactjs.org/) application that uses [Material-UI](https://material-ui.com/). If you are curious, you can take a look at [the whole repository](https://github.com/Tisn/tisn.app).

## Usage

Let's start with the actual tutorial! As I wanted to be able to share different kinds of resources, what made the most sense was to build a reusable component which implemented all the logic and user interface. The JSX of that component looks like this:

```javascript
<Fragment>
  <IconButton color="primary" onClick={(event) => handleClick(event)}>
    <ShareIcon />
  </IconButton>
  <Menu
    anchorEl={anchorEl}
    keepMounted
    open={!!anchorEl}
    onClose={() => handleClose()}
  >
    <MenuItem onClick={() => handleChatsClick()}>
      {t('shareMenu.chats')}
    </MenuItem>
    <MenuItem onClick={() => handleMoreClick()}>
      {t('shareMenu.more')}
    </MenuItem>
  </Menu>
</Fragment>
```

But let's see how all of this works, as just sharing the JSX is not that useful! 😄 First, we have the share button that we'll be presenting to the user (the `IconButton` component) that calls the `handleClick` function on click. This `handleClick` function is the function where we'll check if the Web Share API is supported in the current browser in order to decide what to show to the user:

```javascript
const handleClick = (event) => {
  if (navigator.share) {
    setAnchorEl(event.currentTarget);
  } else {
    handleChatsClick();
  }
};
```

To do that, we simply check for the `navigator.share` method of the API. If it exists, we present the user with a two option menu by setting the anchor element of it. If not, we just call the `handleChatsClick` function. This function is responsible for direct in app sharing through the chat system of the application, and won't be covered in this article to try and stay on topic. Here's where you would implement any fallback mechanism for browsers that don't support the API, but for me direct in app sharing was enough of a fallback.

Let's now see what the `handleMoreClick` function does, which is where the actual Web Share API logic is implemented:

```javascript
const handleMoreClick = () => {
  handleClose();
  navigator.share(params);
};
```

Wow! Easy, right? 😎 We just close the menu with the `handleClose` function (setting the anchor element of it to `null`) and call the `navigator.share` method of the Web Share API with the `params` object. At this point, the user will be presented with the native share menu:

![Native share menu](https://dev-to-uploads.s3.amazonaws.com/i/0165wfz6u1t4ij65dhxx.jpg)

The `params` object passed to the `navigator.share` method comes directly from the properties passed to the component, and it looks like this:

```javascript
params = {
  title: "Title",
  text: "Text",
  url: "URL",
}
```

Given how the data that we pass through the Web Share API is handled by Android (I haven't been able to test this on iOS), I've found out that the best strategy is to have the `title` and `text` be the same string. Also, it's worth noting that the `url` will be appended to the end of `text` -- but this is something that we only have to care about if we want to handle receiving data. Wait, is there an API that allows our application to receive data from other apps? Oh yes, there is! If you want me to write an article about it, let me know it in the comments section and I'll gladly do it! 😊

Besides, the Web Share API allows sharing files with other apps too, although I haven't played with that as it didn't apply to my use case.

## Conclusion

In this article we've gone through a simple implementation of the Web Share API, which allows us to share content of our application with other apps through the native share menu. This API solves the problem of having to rely on external libraries or having to implement custom methods in order to share content of our application with other apps, and although it's not supported by many major browsers, it should work on almost any phone.

I hope this tutorial has been useful for you, let me know it by reacting to it and/or posting a comment. And, of course, thanks for reading!

See you around 👋