Course Dashboard

Lesson 6: Managing & Canceling Notifications

Scheduling a notification is just the beginning. In a production-grade application, you must be able to audit, update, and retract notifications based on the user's actions. If a user deletes a task, their phone shouldn't still buzz 10 minutes later for that same task.

In this lesson, we will learn how to:

  • Audit the Queue: Retrieve all currently scheduled notifications.
  • Targeted Cancellation: Removing specific notifications using their IDs.
  • The "Nuke" Option: Clearing all scheduled alerts at once.
  • Managing Displayed Alerts: Programmatically dismissing notifications already in the system tray.

1. Auditing the Notification Queue

Before you can manage your notifications, you need to see what's currently "in flight." Expo provides getAllScheduledNotificationsAsync, which returns an array of all pending alerts that haven't triggered yet.

index.tstypescript
import * as Notifications from 'expo-notifications';

const auditQueue = async () => {
  const scheduled = await Notifications.getAllScheduledNotificationsAsync();
  
  console.log(`There are ${scheduled.length} notifications in the queue.`);
  
  scheduled.forEach(notif => {
    console.log(`[ID: ${notif.identifier}] Title: ${notif.content.title}`);
  });
};

This is extremely useful for debugging and for building "Reminders Management" screens within your app.


2. Targeted Cancellation

To cancel a specific notification, you must have saved its identifier when it was first scheduled.

[!IMPORTANT] Always store your notification identifiers in your database (SQLite, AsyncStorage, or your backend) alongside the relevant data (like a Task ID). This is the only way to link a user action (like "Delete Task") to its scheduled alert.

index.tstypescript
const cancelTaskReminder = async (notificationId: string) => {
  await Notifications.cancelScheduledNotificationAsync(notificationId);
  console.log(`Notification ${notificationId} has been retracted.`);
};

3. The "Clear All" Strategy

There are scenarios where you want to start fresh—such as when a user logs out or disables all reminders in the settings.

index.tstypescript
const deactivateAllReminders = async () => {
  await Notifications.cancelAllScheduledNotificationsAsync();
  // UI feedback to user
};

Use this carefully, as it will remove every single pending notification from your app, including ones the user might still expect.


4. Dismissing Delivered Notifications

Sometimes, a notification has already fired and is sitting in the user's notification drawer. If the user opens the app and completes the task, those old notifications are now stale. You can clean them up programmatically.

index.tstypescript
// Clear all notifications currently visible in the system tray
await Notifications.dismissAllNotificationsAsync();

// Clear one specific visible notification
await Notifications.dismissNotificationAsync(id);

On Android, this is particularly powerful for keeping the user's status bar clean and relevant.


Integration with Your Data Store

The most professional way to handle this is by creating a wrapper function that handles both the data update and the notification logic:

index.tstypescript
async function deleteAndCancelTask(taskId: string, notificationId: string) {
  // 1. Remove from Database
  await db.tasks.delete(taskId);
  
  // 2. Cancel the Alert
  if (notificationId) {
    await Notifications.cancelScheduledNotificationAsync(notificationId);
  }
}

Your Challenge

Implement an "Audit" button in your project that logs out all pending notifications. Then, try scheduling 3 notifications and canceling the middle one using its ID. Verify that only 2 remain in the queue.