Skip to content

Instantly share code, notes, and snippets.

@achadha235
Last active November 19, 2024 06:18
Show Gist options
  • Select an option

  • Save achadha235/e986363348eabfb5191dbe392c90bf36 to your computer and use it in GitHub Desktop.

Select an option

Save achadha235/e986363348eabfb5191dbe392c90bf36 to your computer and use it in GitHub Desktop.
React hook for managing web push notifications
import { useEffect, useState } from "react";
enum NotificationError {
ServiceWorkerAndPushManagerNotSupported = "ServiceWorkerAndPushManagerNotSupported",
PushManagerUnavailable = "PushManagerUnavailable",
ExistingSubscription = "ExistingSubscription",
PermissionNotGranted = "PermissionNotGranted",
}
export function useNotifications() {
const [loading, setLoading] = useState(true);
const [subscription, setSubscription] = useState<PushSubscription | null>(
null
);
const isNotificationSupported =
"serviceWorker" in navigator && "PushManager" in window;
async function useServiceWorkerRegistration() {
return navigator.serviceWorker.ready;
}
useEffect(() => {
if (!isNotificationSupported) {
setLoading(false);
return;
}
async function checkExistingSubscription() {
try {
const registration = await useServiceWorkerRegistration();
const pushManager = registration.pushManager;
if (pushManager) {
const existingSubscription = await pushManager.getSubscription();
if (existingSubscription) {
setSubscription(existingSubscription);
}
}
} catch (error) {
console.error("Error checking subscription:", error);
} finally {
setLoading(false);
}
}
checkExistingSubscription();
}, []);
async function subscribe(options: PushSubscriptionOptionsInit) {
setLoading(true);
try {
if (!isNotificationSupported) {
throw new Error(
NotificationError.ServiceWorkerAndPushManagerNotSupported
);
}
const permission = await Notification.requestPermission();
if (permission !== "granted") {
throw new Error(NotificationError.PermissionNotGranted);
}
const registration = await useServiceWorkerRegistration();
const pushManager = registration.pushManager;
if (!pushManager) {
throw new Error(NotificationError.PushManagerUnavailable);
}
const existingSubscription = await pushManager.getSubscription();
if (existingSubscription) {
throw new Error(NotificationError.ExistingSubscription);
}
const subscription = await pushManager.subscribe(options);
console.debug("subscription", subscription);
setSubscription(subscription);
} finally {
setLoading(false);
}
}
async function unsubscribe() {
setLoading(true);
try {
if (!isNotificationSupported) {
throw new Error(
NotificationError.ServiceWorkerAndPushManagerNotSupported
);
}
const registration = await useServiceWorkerRegistration();
const pushManager = registration.pushManager;
if (!pushManager) {
throw new Error(NotificationError.PushManagerUnavailable);
}
const existingSubscription = await pushManager.getSubscription();
if (!existingSubscription) {
return false;
}
const success = await existingSubscription.unsubscribe();
if (success) {
setSubscription(null);
}
return success;
} finally {
setLoading(false);
}
}
return {
subscription,
isNotificationSupported,
subscribe,
unsubscribe,
loading,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment