🎀

Safari 通知権限チェック処理エラー解消メモ

2024/06/01に公開

エラーの内容

 Notification prompting can only be done from a user gesture.

問題のあるコード

'use client';

import { useEffect, useState } from 'react';

const useNotificationPermissionStatus = () => {
  const [notificationPermissionStatus, setNotificationPermissionStatus] =
    useState('');

  useEffect(() => {
    const getNotificationPermissionStatus = () => {
      if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
        // 通知許可をリクエストする
        Notification.requestPermission()
          .then((permission) => {
            setNotificationPermissionStatus(permission);
          })
          .catch((e) => {
            console.error('Notification権限取得失敗', e);
          });
      }
    };

    getNotificationPermissionStatus();
  }, []);

  return notificationPermissionStatus;
};

export default useNotificationPermissionStatus;

事象

通知権限のチェックの処理をChromeやArcで実行しても問題ないですが、Safariで上記のエラーに遭遇しました。

解消するためのコード

// 'use client';
import { useEffect, useState } from 'react';

const useNotificationPermissionStatus = () => {
  const [notificationPermissionStatus, setNotificationPermissionStatus] =
    useState('');
  const [isNotified, setIsNotified] = useState(false);

  useEffect(() => {
    if (
      typeof window !== 'undefined' &&
      'serviceWorker' in navigator &&
      !isNotified
    ) {
      // このあたり
      window.addEventListener('load', function getNotificationPermissionStatus() {
        window.removeEventListener('load', getNotificationPermissionStatus);

        // 通知許可をリクエストする
        Notification.requestPermission()
          .then((permission) => {
            setNotificationPermissionStatus(permission);
          })
          .catch((e) => {
            console.error('Notification権限取得失敗', e);
          });

        setIsNotified(true);
      });
    }
  }, [isNotified]);

  return notificationPermissionStatus;
};

export default useNotificationPermissionStatus;

一応上記にeventをadd&remove したら、エラー解消しましたが、何かしらユーザーに合意を取るアクションが求められるはずなので、'click'イベントのほうがいいかもしれません😲

環境

    "next": "14.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",

Discussion