npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@silicon.js/push-notifications

v1.0.9

Published

A React Native package for managing push notifications using Expo Notifications with a simple provider-based architecture.

Readme

Push Notifications Package

A React Native package for managing push notifications using Expo Notifications with a simple provider-based architecture.

Features

  • 🔔 Easy-to-use React Context API for push notifications
  • 🎯 Permission management with status tracking
  • 🔄 Automatic token refresh and synchronization
  • 💾 Token caching to avoid redundant API calls
  • 📱 Cross-platform support (iOS & Android)
  • 🎨 Customizable notification channels (Android)
  • ⚡ App state change detection for token updates

Installation

npm install expo-notifications expo-application @react-native-async-storage/async-storage

Setup

1. Wrap your app with the provider

import { PushNotificationsProvider } from './push-notifications';

function App() {
  return (
    <PushNotificationsProvider
      projectID="your-expo-project-id"
      onSendToken={async (params) => {
        // Send token to your backend
        const response = await api.post('/push-tokens', params);
        return response.data;
      }}
      onDisableToken={async (params) => {
        // Disable token on your backend
        await api.delete(`/push-tokens/${params.deviceId}`);
      }}
      getTokenFromResponse={(response) => response.token}
    >
      {/* Your app components */}
    </PushNotificationsProvider>
  );
}

2. Use the hook in your components

import { usePushNotificationsContext } from './push-notifications';

function NotificationSettings() {
  const { token, permission, isPermissionGranted, requestPermission, sendToken, updateTokenIfNeeded } =
    usePushNotificationsContext();

  const handleEnableNotifications = async () => {
    const status = await requestPermission();

    if (status === 'granted') {
      await updateTokenIfNeeded();
    }
  };

  return (
    <View>
      <Text>Permission: {permission?.status}</Text>
      <Text>Token: {token}</Text>
      <Button onPress={handleEnableNotifications} title="Enable Notifications" />
    </View>
  );
}

API Reference

PushNotificationsProvider Props

| Prop | Type | Required | Description | | ---------------------- | -------------------------------------------------- | -------- | ----------------------------------------------------------- | | projectID | string | Yes | Your Expo project ID | | onSendToken | (params: CreatePushTokenDto) => Promise<unknown> | Yes | Callback to send token to your backend | | onDisableToken | (params: DisablePushTokenDto) => Promise<void> | Yes | Callback to disable token on your backend | | getTokenFromResponse | (response: Record<string, unknown>) => string | No | Extract token from API response (default: response.token) | | children | React.ReactNode | Yes | Child components | | fallback | React.ReactNode | No | Fallback UI while loading |

Context Values

State

  • token: string | null - The current push notification token
  • permission: PermissionDetails | null - Current permission status and details
  • isPermissionGranted: boolean - Quick check if permission is granted

Methods

  • requestPermission(options?: GetPermissionOptions): Promise<PushNotificationsPermissionStatusEnum>

    • Request push notification permissions from the user
    • Returns the permission status
  • sendToken(params: CreatePushTokenDto): Promise<void>

    • Manually send token to your backend
    • Automatically caches the sent token
  • disableToken(params: DisablePushTokenDto): Promise<void>

    • Disable token on your backend
    • Clears the cached token
  • updateTokenIfNeeded(): Promise<void>

    • Checks if the current token differs from the last sent token
    • Automatically sends the token if it has changed
  • clearPushTokenCache(): Promise<void>

    • Clears the locally cached token
    • Useful for testing or manual cache management

Types

CreatePushTokenDto

interface CreatePushTokenDto {
  token: string;
  deviceId: string;
}

DisablePushTokenDto

interface DisablePushTokenDto {
  deviceId: string;
}

PermissionDetails

interface PermissionDetails {
  status: PushNotificationsPermissionStatusEnum;
  canAskAgain: boolean;
}

PushNotificationsPermissionStatusEnum

enum PushNotificationsPermissionStatusEnum {
  Granted = 'granted',
  Denied = 'denied',
  Undetermined = 'undetermined',
}

GetPermissionOptions

interface GetPermissionOptions {
  channelConfig?: Partial<Notifications.NotificationChannelInput>;
  permissionsRequest?: Notifications.NotificationPermissionsRequest;
}

Advanced Usage

Custom Notification Channel (Android)

const status = await requestPermission({
  channelConfig: {
    name: 'Important Updates',
    importance: Notifications.AndroidImportance.HIGH,
    sound: 'notification.wav',
    vibrationPattern: [0, 250, 250, 250],
  },
});

Handling Token Updates

The package automatically handles token updates when:

  • App returns to foreground
  • Permission is granted
  • Token is refreshed

You can also manually trigger updates:

useEffect(() => {
  updateTokenIfNeeded();
}, [updateTokenIfNeeded]);

Storage

The package uses AsyncStorage to cache the last sent token under the key STORAGE_KEYS.LAST_SENT_TOKEN. This prevents unnecessary API calls when the token hasn't changed.

Platform-Specific Notes

Android

  • Automatically creates a default notification channel
  • Uses Application.getAndroidId() for device identification

iOS

  • Uses Application.getIosIdForVendorAsync() for device identification
  • Requires proper entitlements for push notifications

Error Handling

Always wrap push notification operations in try-catch blocks:

try {
  await updateTokenIfNeeded();
} catch (error) {
  console.error('Failed to update push token:', error);
  // Handle error appropriately
}

Best Practices

  1. Request permissions contextually - Don't ask for permissions immediately on app launch
  2. Handle denials gracefully - Provide UI to guide users to settings if needed
  3. Test on real devices - Push notifications don't work on simulators/emulators
  4. Monitor token changes - The package handles this automatically, but be aware tokens can change
  5. Clean up tokens - Call disableToken() on logout or when notifications should be disabled