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>
)
}