Fiber UI LogoFiberUI

useShare

A cross-platform utility hook for invoking the native share sheet on mobile and desktop, enabling effortless content sharing with optional fallbacks.

Installation

npx shadcn@latest add https://r.fiberui.com/r/hooks/use-share.json

A React hook that provides access to the Web Share API, allowing you to trigger the native share mechanism of the device (like the share sheet on iOS/Android).

Source Code

View the full hook implementation in the Hook Source Code section below.

Requirements

  • Requires HTTPS (secure context). - Requires User Interaction (click handler) to trigger. - Support varies by browser/OS (mostly Mobile + Safari desktop).

Features

  • Native Experience - Triggers the system share sheet users are familiar with
  • File Sharing - Supports sharing files (images, pdfs, etc)
  • Support Check - isSupported flag to conditionally render UI
  • Cancellation Handling - Gracefully handles user cancellation
  • SSR Safe - Works safely with server-side rendering

Basic Usage

Share a title, text, and URL. This works on most mobile browsers and Safari on macOS.

Web Share API is not supported in this browser.
"use client";

import { useShare } from "@repo/hooks/utility/use-share";
import { Button } from "@repo/ui/components/button";
import { Share2 } from "lucide-react";
import { toast } from "sonner";

export function Example1() {
    const { share, isSupported } = useShare();

    const handleShare = async () => {
        const success = await share({
            title: "Fiber UI Hooks",
            text: "Check out this awesome collection of React hooks!",
            url: "https://fiberui.com/hooks",
        });

        if (success) {
            toast.success("Shared successfully!");
        } else {
            toast.error("Share cancelled or failed");
        }
    };

    if (!isSupported) {
        return (
            <div className="rounded-md bg-yellow-100 p-4 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-200">
                Web Share API is not supported in this browser.
            </div>
        );
    }

    return (
        <Button onClick={handleShare} className="gap-2">
            <Share2 className="h-4 w-4" />
            Share Resource
        </Button>
    );
}

API Reference

Hook Signature

function useShare(): UseShareReturn;

ShareData Interface

interface ShareData {
    title?: string; // Title of the shared content
    text?: string; // Description text
    url?: string; // URL to share
    files?: File[]; // Array of File objects to share
}

Return Value

PropertyTypeDescription
share(data: ShareData) => Promise<boolean>Triggers share sheet. Returns true if successful
isSupportedbooleantrue if Web Share API is available on current device
isSharingbooleantrue while the share sheet is open (some browsers)
canShare(data: ShareData) => booleanChecks if specific data (like files) can be shared
errorError | nullError object if share failed or was cancelled

Hook Source Code

import { useState, useCallback } from "react";

/**
 * Options for the share data
 */
export interface ShareData {
    /** Title of the shared content */
    title?: string;
    /** Text description of the shared content */
    text?: string;
    /** URL to share */
    url?: string;
    /** Array of files to share */
    files?: File[];
}

/**
 * Return type for the useShare hook
 */
export interface UseShareReturn {
    /** Share data using the native share sheet */
    share: (data: ShareData) => Promise<boolean>;
    /** Whether sharing is supported */
    isSupported: boolean;
    /** Whether a share operation is in progress */
    isSharing: boolean;
    /** Error from the last share attempt */
    error: Error | null;
    /** Check if specific data can be shared */
    canShare: (data: ShareData) => boolean;
}

/**
 * A React hook for using the Web Share API to share content via the triggering device's native sharing mechanism.
 *
 * @returns UseShareReturn object with share function and state
 *
 * @example
 * ```tsx
 * const { share, isSupported } = useShare();
 *
 * return (
 *     <button onClick={() => share({ title: "Check this out", url: "https://example.com" })}>
 *         Share
 *     </button>
 * );
 * ```
 */
export function useShare(): UseShareReturn {
    const [isSharing, setIsSharing] = useState(false);
    const [error, setError] = useState<Error | null>(null);

    // Check support
    const isSupported =
        typeof navigator !== "undefined" &&
        typeof navigator.share === "function";

    // Can share check
    const canShare = useCallback((data: ShareData): boolean => {
        if (
            typeof navigator === "undefined" ||
            typeof navigator.canShare !== "function"
        ) {
            return false;
        }
        return navigator.canShare(data);
    }, []);

    // Share function
    const share = useCallback(
        async (data: ShareData): Promise<boolean> => {
            if (!isSupported) {
                setError(new Error("Web Share API is not supported"));
                return false;
            }

            setIsSharing(true);
            setError(null);

            try {
                await navigator.share(data);
                return true;
            } catch (err) {
                // AbortError is common when user cancels, we treat it as an error but you might want to ignore it
                const error =
                    err instanceof Error ? err : new Error("Failed to share");
                setError(error);
                return false;
            } finally {
                setIsSharing(false);
            }
        },
        [isSupported],
    );

    return {
        share,
        isSupported,
        isSharing,
        error,
        canShare,
    };
}

export default useShare;