Web Share Web API
- Authors
- Name
- Austin Howard
- Published on
- Updated on
If sharing text, urls, or files is an important part of your web application, your goal should be to make sharing as convenient as possible for your users. A great tool for this is the Web Share API. The Web Share API allows you to trigger the native sharing capabilities of the device. This means that you can use it share to other apps on the device, such as email, messaging, and social media apps.
Example
Here is a simple example of how you can use the Web Share API to share text, urls and files.
The useWebShare
hook below allows passing in an object with the following properties:
title
- The title of the shared content.text
- The text of the shared content.url
- The URL of the shared content.files
- An array of string URLs to files that should be shared.
Some environments and devices may not support sharing files. In this case, the files
property will be ignored, and only the title
, text
, and url
properties will be shared.
// use-webshare.tsx
export type PreFilesShareData = {
title?: string
text?: string
url?: string
files?: string[]
}
export type WebShareData = {
title?: string
text?: string
url?: string
files?: File[]
}
export const useWebShare = () => {
const share = async (data: PreFilesShareData) => {
if (!navigator.share) {
console.error('Web Share API not supported.')
return null
}
if (!data.files?.length) {
try {
await navigator.share({ title: data.title, text: data.text, url: data.url })
} catch (error) {
console.error('Error sharing:', error)
}
return
}
let dataWithFiles: WebShareData = {
...data,
files: [],
}
const fetchErrors = []
if (data?.files) {
for (const url of data.files) {
try {
const fullUrl = new URL(url, window.location.origin)
const fileName = fullUrl.pathname.split('/').pop()
const response = await fetch(fullUrl)
const blob = await response.blob()
dataWithFiles.files.push(new File([blob], fileName, { type: blob.type }))
} catch (error) {
fetchErrors.push({ url, error })
}
}
if (fetchErrors.length > 0) {
console.warn('Some files could not be fetched:', fetchErrors)
}
if (!navigator.canShare({ files: dataWithFiles.files })) {
console.error('The browser does not support sharing these files.', dataWithFiles.files)
const fallbackUrl = new URL(data.files[0], window.location.origin).href
dataWithFiles.url = fallbackUrl
delete dataWithFiles.files
}
try {
await navigator.share(dataWithFiles)
} catch (error) {
console.error('Error sharing:', error)
}
}
}
return { share }
}
Here is how you can use the useWebShare
hook in a React component:
// implementation
import { useWebShare, PreFilesShareData } from '@/lib/sharing/use-webshare'
import { ReactNode } from 'react'
export type Props = {
children: ReactNode
} & PreFilesShareData
export const ShareButton = ({ title = 'Default title', text, url, files, children }: Props) => {
const { share } = useWebShare()
return <button onClick={() => share({ title, text, url, files })}>{children}</button>
}
Keep in mind that the user must trigger the share action. You cannot trigger the share action programmatically. See transient activation for more information.