Triggers

Understand how to use triggers to create notifications that fire under specific conditions.

Triggers can be used to display notifications in-advance when a specific condition is met such as time.

For example, you may wish to notify your user when they have a meeting at work.

Handling trigger notifications

Creating a trigger notification

import React from 'react';
import { View, Button } from 'react-native';
import notifee, { TimestampTrigger, TriggerType } from 'react-native-notify-kit';

function Screen() {
  async function onCreateTriggerNotification() {
    const date = new Date(Date.now());
    date.setHours(11);
    date.setMinutes(10);

    // Create a time-based trigger
    const trigger: TimestampTrigger = {
      type: TriggerType.TIMESTAMP,
      timestamp: date.getTime(), // fire at 11:10am (10 minutes before meeting)
    };

    // Create a trigger notification
    await notifee.createTriggerNotification(
      {
        title: 'Meeting with Jane',
        body: 'Today at 11:20am',
        android: {
          channelId: 'your-channel-id',
        },
      },
      trigger,
    );
  }

  return (
    <View>
      <Button title="Create Trigger Notification" onPress={() => onCreateTriggerNotification()} />
    </View>
  );
}

To see a full list of triggers and their properties, view the Trigger reference documentation.

The createTriggerNotification method is called passing in a notification and a trigger. You must ensure the channel is created first as well as other attributes your notification may have such as categories.

Go ahead and press the button! A notification will appear in 10 minutes, giving the user a reminder they have a meeting with Jane!

Updating a trigger notification

Trigger notifications work in the same way as any other notification. They have a random unique ID assigned to them which can be used to update pending trigger notifications. If there is no trigger with that ID, a new one will be created.

Let's update our trigger we created previously to occur weekly.

import notifee, { TimestampTrigger, TriggerType, RepeatFrequency } from 'react-native-notify-kit';

async function onCreateTriggerNotification() {
  const date = new Date(Date.now());
  date.setHours(11);
  date.setMinutes(10);

  const trigger: TimestampTrigger = {
    type: TriggerType.TIMESTAMP,
    timestamp: date.getTime(),
    repeatFrequency: RepeatFrequency.WEEKLY,
  };

  await notifee.createTriggerNotification(
    {
      id: '123',
      title: 'Meeting with Jane',
      body: 'Today at 11:20am',
      android: {
        channelId: 'your-channel-id',
      },
    },
    trigger,
  );
}

To update any notifications that are already displayed, you can update them using displayNotification

Retrieving trigger notifications

To retrieve a list of all your trigger notifications you can call getTriggerNotificationIds method and a list of ids will be returned.

notifee.getTriggerNotificationIds().then(ids => console.log('All trigger notifications: ', ids));

Cancelling a trigger notification

There may be situations whereby you may want to cancel the trigger notification and stop any future notifications from displaying.

To cancel a trigger notification, the cancelNotification method can be called with the unique notification ID.

It's also possible to cancel all of your trigger notifications, by calling cancelTriggerNotifications or cancelAllNotifications.

Trigger Types

Timestamp Trigger

The TimestampTrigger allows you to create a trigger that displays a notification at a specific time and date, using the property timestamp (milliseconds since epoch) and optional repeatFrequency and repeatInterval properties:

import notifee, {
  TimestampTrigger,
  TriggerType,
  RepeatFrequency,
  TimeUnit,
  AlarmType,
} from 'react-native-notify-kit';

const trigger: TimestampTrigger = {
  type: TriggerType.TIMESTAMP,
  timestamp: Date.now() + 1000 * 60 * 60 * 3, // fire in 3 hours
  repeatFrequency: RepeatFrequency.WEEKLY, // repeat once a week
};

Custom repeat intervals

Timestamp triggers now support custom repeat intervals. Use repeatFrequency to choose the calendar unit and repeatInterval as a positive integer multiplier for that unit.

repeatInterval defaults to 1 when repeatFrequency is set. repeatInterval is only valid with a repeating repeatFrequency; it is not valid without repeatFrequency or with RepeatFrequency.NONE. Supported timestamp repeat frequencies are HOURLY, DAILY, WEEKLY, and MONTHLY; YEARLY is not supported.

repeatFrequencyrepeatIntervalResult
RepeatFrequency.DAILY2every 2 days
RepeatFrequency.WEEKLY2every 2 weeks
RepeatFrequency.MONTHLY3every 3 months
const firstOccurrence = new Date();
firstOccurrence.setHours(10, 0, 0, 0);

await notifee.createTriggerNotification(
  {
    title: 'Reminder',
    body: 'This reminder repeats every 2 days.',
    android: { channelId: 'reminders' },
  },
  {
    type: TriggerType.TIMESTAMP,
    timestamp: firstOccurrence.getTime(),
    repeatFrequency: RepeatFrequency.DAILY,
    repeatInterval: 2,
  },
);
const firstOccurrence = new Date();
firstOccurrence.setHours(12, 45, 0, 0);

await notifee.createTriggerNotification(
  {
    title: 'Quarterly reminder',
    body: 'This reminder repeats every 3 months.',
    android: { channelId: 'reminders' },
  },
  {
    type: TriggerType.TIMESTAMP,
    timestamp: firstOccurrence.getTime(),
    repeatFrequency: RepeatFrequency.MONTHLY,
    repeatInterval: 3,
  },
);

Android behavior

On Android, repeatInterval is used together with repeatFrequency to advance the next timestamp with calendar-aware scheduling. For example, RepeatFrequency.DAILY with repeatInterval: 2 advances by two calendar days, and RepeatFrequency.MONTHLY with repeatInterval: 3 advances by three calendar months.

AlarmManager is the default and recommended backend for timestamp triggers. RepeatFrequency.MONTHLY is supported with AlarmManager. RepeatFrequency.MONTHLY is not supported with alarmManager: false, because WorkManager uses duration-based intervals and does not provide calendar-month semantics.

For reminders where the timing is important, consider AlarmType.SET_ALARM_CLOCK. It is not required for every timestamp trigger, but it uses Android's highest-priority scheduled alarm primitive.

const firstOccurrence = new Date();
firstOccurrence.setHours(10, 0, 0, 0);

await notifee.createTriggerNotification(
  {
    title: 'Reminder',
    body: 'Your scheduled reminder is due.',
    android: {
      channelId: 'reminders',
    },
  },
  {
    type: TriggerType.TIMESTAMP,
    timestamp: firstOccurrence.getTime(),
    repeatFrequency: RepeatFrequency.DAILY,
    repeatInterval: 2,
    alarmManager: {
      type: AlarmType.SET_ALARM_CLOCK,
    },
  },
);

iOS behavior change for repeating timestamp triggers

On iOS, repeating timestamp triggers use a bounded rolling schedule of one-shot local notifications. This replaces the previous native repeating UNCalendarNotificationTrigger path for repeating timestamp triggers.

This behavior change applies only to repeating TimestampTrigger notifications on iOS. Android scheduling and one-shot timestamp triggers keep their existing paths.

This is intentional: native repeating calendar triggers cannot express custom intervals such as every 2 days or every 3 months from a selected start timestamp, and they can match the next wall-clock time even when the intended start date is in the future.

The rolling schedule keeps upcoming occurrences pending and tops them up when the app becomes active, when the user interacts with a notification, or when a rolling notification is delivered while the app is in the foreground. Because iOS does not wake the app merely because a local notification was delivered while the app is killed or suspended, the rolling window cannot be extended indefinitely unless the app runs again.

When multiple rolling timestamp triggers are active, the library rebalances the bounded rolling window across active rolling series. Earlier triggers do not consume the entire pending-notification budget and block later triggers. If the number of active rolling series exceeds the available rolling budget, scheduling fails with a clear error instead of silently dropping existing series. Non-rolling pending notifications created by the app still count against iOS' global pending-notification limits, so they reduce the space available for rolling timestamp triggers.

This rolling schedule respects the selected start date. It does not use a native repeating UNCalendarNotificationTrigger for custom repeat intervals. Internal rolling notification IDs are not exposed through the JavaScript APIs; APIs such as getTriggerNotificationIds() and getDisplayedNotifications() use the public notification IDs.

Monthly repeats and month-end dates

Monthly repeats use native calendar semantics. Dates that do not exist in a target month are adjusted by the platform calendar. For example, a trigger starting on January 31 and repeating monthly may move to the last valid day of February, depending on platform calendar behavior.

Android backend: AlarmManager (default) vs WorkManager

Since v9.1.12, Android trigger notifications are scheduled with AlarmManager by default — this gives reliable delivery even when the app is killed, which WorkManager cannot guarantee on aggressive OEM ROMs. The default AlarmType is SET_EXACT_AND_ALLOW_WHILE_IDLE, which also fires during Doze mode.

You can opt out and fall back to WorkManager with alarmManager: false, or customise the AlarmManager configuration with an object:

const trigger: TimestampTrigger = {
  type: TriggerType.TIMESTAMP,
  timestamp: Date.now() + 1000 * 60 * 60 * 3,
  // opt out — use WorkManager (less reliable when app is killed)
  alarmManager: false,
};

const customTrigger: TimestampTrigger = {
  type: TriggerType.TIMESTAMP,
  timestamp: Date.now() + 1000 * 60 * 60 * 3,
  alarmManager: {
    // Explicit AlarmType — if omitted defaults to SET_EXACT_AND_ALLOW_WHILE_IDLE.
    type: AlarmType.SET_EXACT_AND_ALLOW_WHILE_IDLE,
    allowWhileIdle: true,
  },
};

AlarmType.SET_ALARM_CLOCK (strongest reliability)

For time-sensitive reminders, recovery timers, or any notification where a miss is user-visible damage, consider AlarmType.SET_ALARM_CLOCK. It is the strongest reliability guarantee Android exposes — it uses the same primitive as the stock Clock app, renders an alarm-clock icon in the status bar, and is the least susceptible to OEM aggressive-kill power management (Xiaomi MIUI, Oppo ColorOS, Huawei EMUI, Vivo FuntouchOS).

const reminderTrigger: TimestampTrigger = {
  type: TriggerType.TIMESTAMP,
  timestamp: Date.now() + 1000 * 60 * 60 * 8, // 8 hours from now
  alarmManager: {
    type: AlarmType.SET_ALARM_CLOCK,
  },
};

Error handling on Android

Since v9.5.0, createTriggerNotification() and cancelTriggerNotifications() resolve their Promises only after the underlying Room write has completed. Two implications:

  • Latency: ~5–15 ms added on a warm database (measured on a Pixel 9 Pro XL). Tight loops scheduling many triggers may see cumulative latency increases.
  • Rejections: Room write errors — SQLiteFullException on a disk-full device, SQLite corruption, schema migration failures — now propagate as JS Promise rejections. Previously these were silently swallowed and the Promise resolved even when the write failed. Wrap trigger scheduling in try/catch if you need to react to persistence failures:
try {
  await notifee.createTriggerNotification(notification, trigger);
} catch (error) {
  console.warn('Failed to schedule trigger:', error);
}

DST and reboot recovery

Repeating triggers (HOURLY / DAILY / WEEKLY / MONTHLY) honor wall-clock time across DST transitions on Android by using calendar-aware scheduling. Scheduled alarms also self-heal after reboot: since v9.6.0 the library detects boot deltas via Settings.Global.BOOT_COUNT and reschedules persisted alarms on OEM devices that suppress BOOT_COMPLETED (Xiaomi MIUI, Oppo ColorOS, Huawei EMUI, Vivo FuntouchOS). Stale non-repeating triggers (timestamp already in the past at recovery time) fire once within a 24-hour grace period and are then deleted; beyond the grace period they're deleted silently.

Maximum TimestampTrigger Count

Android has a system limit of 50 timestamp triggers active at one time. iOS appears to have a limit of 64 timestamp triggers active at one time, but it is not in the official documentation.

iOS rolling schedule limitations

On iOS, repeating timestamp triggers for HOURLY, DAILY, WEEKLY, and MONTHLY are scheduled through the bounded rolling one-shot model described in Custom repeat intervals. This preserves the selected start timestamp, including the first occurrence.

The rolling window is finite because iOS limits how many local notifications can be pending at one time. The library tops up future occurrences when it gets an app lifecycle, interaction, or foreground-delivery opportunity, but it cannot keep extending the schedule while the app remains killed/suspended and the user never interacts with notifications.

Android 12 Limitations

Starting from Android 12, timestamp triggers cannot be created unless user specfically allow the exact alarm permission. Before you create a timestamp trigger, check whether SCHEDULE_EXACT_ALARM permission is allowed by making a call to getNotificationSettings. If alarm is DISABLED, you should educate the user on this permission and ask to enable scheduling alarms. You can then use openAlarmPermissionSettings function to display the Alarms & Reminder settings of your app.

const settings = await notifee.getNotificationSettings();
if (settings.android.alarm == AndroidNotificationSetting.ENABLED) {
  //Create timestamp trigger
} else {
  // Show some user information to educate them on what exact alarm permission is,
  // and why it is necessary for your app functionality, then send them to system preferences:
  await notifee.openAlarmPermissionSettings();
}

Please note that if the user revokes the permission via system preferences, all of the timestamp triggers will be deleted by the system. However, if you check for the permission, notice it is missing, educate the user and they grant permission again, Notify Kit will automatically reschedule the triggers when the user allows the alarm permission again with no need for additional code.

Interval Trigger

The IntervalTrigger allows you to create a trigger that repeats at a specific interval. The trigger accepts two properties, an interval and an optional timeUnit.

This trigger can be used to implement timers.

For example, to set a trigger to repeat every 30 minutes from now:

import notifee, { IntervalTrigger, TriggerType, TimeUnit } from 'react-native-notify-kit';

const trigger: IntervalTrigger = {
  type: TriggerType.INTERVAL,
  interval: 30,
  timeUnit: TimeUnit.MINUTES
};