WebShare APIを未対応ブラウザ やNext.jsでも使えるようにする

WebShare APIを使うことで、ネイティブアプリのようなシェアUIが作れます。 ただしPC向けブラウザなどでは割と対応していないことが多いので、Polyfilを入れる必要があります。 npm i -S share- […]

広告ここから
広告ここまで

目次

    WebShare APIを使うことで、ネイティブアプリのようなシェアUIが作れます。

    ただしPC向けブラウザなどでは割と対応していないことが多いので、Polyfilを入れる必要があります。

    npm i -S share-api-polyfill

    今回追加したPolyfilです。

    Reactであれば、App.tsxなどでimportしておきましょう。

    import 'share-api-polyfill';

    CapacitorでWebShare APIを使う

    とりあえず動かしてみたいというところが大きかったので、Capacitorで手軽に動かします。

    $npm i -S @capacitor/core

    Reactの場合はこういうHookを作ると良いでしょう。

    import { Plugins } from '@capacitor/core';
    const { Share } = Plugins;
    
      const useShareTheURL = useCallback(() => {
        Share.share({
          title: '共有したいページのタイトル',
          text: 'この記事がお勧めですよ。みたいなことをここに書いておく',
          url: window.location.href,
          dialogTitle: 'Share the page',
        });
      }, []);

    未対応ブラウザでもこういう画面が表示されるようになります。

    [2021/8/23 追記] Next.js他SSRがあるフレームワークで使う方法

    このPolifilですが、window.navigatorを利用する関係かSSRが絡むフレームワークを使うと以下のエラーがでます。

    Server Error
    ReferenceError: navigator is not defined
    This error happened while generating the page. Any console logs will be displayed in the terminal window.

    WebComponentの読み込みなどと同じく、これもuseEffectを使ってクライアント側読み込みに変更すればOKです。

        useEffect(() => {
            require('share-api-polyfill')
        },[])

    厳密に読み込み管理をしたい場合は、Providerを作ると良いかなと思います。

    
    const ShareContext = createContext<{
        polifilLoaded: boolean;
    }>({
        polifilLoaded: false
    })
    
    export const useWebShare = () => {
        const context = useContext(ShareContext)
        if (!context) {
            throw new Error('Web Share component can not be use outside the WebShareProvider component')
        }
        const { polifilLoaded } = context
        return {
            createHook: (option: ShareOptions) => {
                return useCallback(async() => {
                    if (!polifilLoaded && (!window || !window.navigator)) {
                        throw new Error(
                            'Share API not available in this browser'
                        )
                    }
                    await Share.share(option)
                },[option, polifilLoaded])
            },
            polifilLoaded,
        }
    }
    
    export const WebShareProvider:FC = ({children}) => {
        const [polifilLoaded, setPolifilLoaded] = useState(false)
        useEffect(() => {
            try {
                require('share-api-polyfill')
                setPolifilLoaded(true)
            } catch (e) {
                setPolifilLoaded(false)
            }
        },[setPolifilLoaded])
        const value = useMemo(() => {
            return {polifilLoaded}
        },[polifilLoaded])
        return (
            <ShareContext.Provider value={value}>
                {children}
            </ShareContext.Provider>
        )
    }

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark