30% offEnding soon
useNotificationLoading saved progress…

useNotification

The useNotification hook exposes the browser's current notification permission together with explicit operations for requesting permission and displaying a notification. You will wrap the Notifications API without touching browser globals during the first render. The hook must keep permission requests under caller control because browsers expect them to follow a user interaction such as a button click. It must also distinguish an unsupported environment from the browser's three permission values.

Signature

type NotificationPermissionState =
  | 'default'
  | 'granted'
  | 'denied'
  | 'unsupported';

function useNotification(): {
  isSupported: boolean;
  permission: NotificationPermissionState;
  requestPermission: () => Promise<'default' | 'granted' | 'denied'>;
  showNotification: (
    title: string,
    options?: NotificationOptions
  ) => Notification;
};

Examples

const notifications = useNotification();

// In a supporting browser whose user has not decided yet:
notifications.isSupported; // true
notifications.permission;  // 'default'

// Call from a click handler, not during render or mount.
await notifications.requestPermission(); // 'granted'
const notice = notifications.showNotification('Build complete', {
  body: 'Version 2.4 is ready.',
});
// notice is the exact Notification instance created by the browser.

If permission is still 'default' or has become 'denied', showNotification() throws instead of calling the constructor. If the browser rejects the permission request or the constructor itself fails, preserve that original error for the caller.

Notes

  • Start safely — the first render returns false and 'unsupported'; after mount, reconcile from window.Notification.permission.
  • Never prompt automatically — only requestPermission() may call the browser prompt, and the caller is responsible for invoking it from a user interaction.
  • Read at call timeshowNotification() must check the browser's current static Notification.permission, not a possibly stale React snapshot.
  • Preserve failures — missing APIs produce clear errors, while browser promise and constructor errors pass through unchanged.
  • Keep callbacks stablerequestPermission and showNotification keep the same identity across rerenders.
  • Return useful results — return the resolved permission from requestPermission() and the exact instance from showNotification().
  • Stay focused — service workers, push subscriptions, permission polling, mobile fallbacks, and automatic closing are out of scope.