---
title: Events
description: Handling notification and device events.
---

Notification & device events are an important concept as they allow applications to react to events (e.g. a user pressing
a displayed notification and changing the in-app screen).

## Listening for events

Using Notify Kit it is possible to display notifications in various situations, for example via [Headless JS](https://facebook.github.io/react-native/docs/headless-js-android)
tasks, directly from your application (e.g. Button press) or via 3rd party services such as [FCM](/react-native/integrations/fcm).

This flexibility opens up a key challenge for React Native developers; handling events when the application is both
active & killed. Notify Kit provides a simple API for handling both scenarios.

## Foreground Events

An application is deemed in the "foreground" only under the following situation:

- The device is unlocked, and the application is running & is in view (foreground).

In any other situation a [Background Event](/react-native/events#background-events) is used instead. If the user
has opened your application and switched to another task (e.g. opened another app, pressed the "home" button) but not
closed/quit your application, it is still classed as being in the background.

To handle foreground events, the [`useEffect`](https://reactjs.org/docs/hooks-effect.html) hook can be used with the
[`onForegroundEvent`](/react-native/reference/onforegroundevent) method:

```jsx
import { useEffect } from 'react';
import notifee, { EventType } from 'react-native-notify-kit';

function App() {
  // Subscribe to events
  useEffect(() => {
    return notifee.onForegroundEvent(({ type, detail }) => {
      switch (type) {
        case EventType.DISMISSED:
          console.log('User dismissed notification', detail.notification);
          break;
        case EventType.PRESS:
          console.log('User pressed notification', detail.notification);
          break;
      }
    });
  }, []);
}
```

> To view all event types, view the [EventType](/react-native/reference/eventtype) documentation.

The foreground event handler runs inside of our React Native code, allowing you to update the application UI or perform
asynchronous actions such as performing a HTTP request.

To learn about handling user interaction with events, view the [Android Interaction](/react-native/android/interaction)
documentation.

> **iOS tap routing.** On iOS, a tap on a notification while the app is in **background or killed** is routed to `onBackgroundEvent` — not `onForegroundEvent` — even though iOS then brings the app to the foreground. At the moment iOS delivers the tap to the `UNUserNotificationCenter` delegate, `UIApplication.applicationState` is `Inactive` (not `Active`), so the routing is based on "app was not active when the tap happened". Register **both** handlers if you need to react to taps in every app state. See [iOS Interaction → Foreground vs background routing](/react-native/ios/interaction#foreground-vs-background-routing) for the native-side detail. Resolves the confusion reported in upstream [invertase/notifee#1155](https://github.com/invertase/notifee/issues/1155).

### Android event buffering and ReactContext transitions

On Android, registering `onForegroundEvent()` initializes the native event relay, so no warm-up call to another native API is required. If an event arrives while the `ReactContext` is unavailable, the relay adds it to the pending event buffer. If the `ReactContext` becomes null or inactive after a flush has taken its snapshot, an event that was not emitted is requeued. This preserves the event for a later flush and prevents it from being permanently discarded.

The next native event relay flush makes another delivery attempt. In the validated recovery path, the event is delivered exactly once, while the existing FIFO order, capacity of 10 pending events, and drop-oldest policy are preserved. Existing application code does not need to change; continue registering foreground and background handlers in the recommended locations. This hardens the Android event path investigated in [react-native-notify-kit#47](https://github.com/marcocrupi/react-native-notify-kit/issues/47) and is related to the event reliability and buffering problem described in upstream [invertase/notifee#1279](https://github.com/invertase/notifee/issues/1279); the scenarios are not necessarily identical.

### Unsubscribing

The `onForegroundEvent` method returns a function which can be used to unsubscribe from future events:

```js
const unsubscribe = notifee.onForegroundEvent(...);

// Sometime later...
unsubscribe();
```

## Background events

An application is deemed in the "background" under the following situations:

- The device is locked.
- The application is running & is not in view (minimized).
- The application is killed/quit.

The [`onBackgroundEvent`](/react-native/reference/onbackgroundevent) method is used to register a callback handler
which will be executed whenever a background event is sent. Executing the callback handler in the background requires
device resources so it is important that any code is executed efficiently & quickly.

> To run long running tasks on Android, view the [Foreground Service](/react-native/android/foreground-service) documentation.

Background tasks run without React context, meaning you cannot update your application UI. You can however perform logic
to update a remote database, update local device storage or even display/update a notification with Notify Kit! An example
of a background event would be handling a "Mark as read" action by updating your database and cancelling the notification.

Only a single background event handler can be registered. To register your handler, the [`onBackgroundEvent`](/react-native/reference/onbackgroundevent)
method should be registered as early on in your project as possible (e.g. the `index.js` file):

```js
// index.js
import { AppRegistry } from 'react-native';
import notifee, { EventType } from 'react-native-notify-kit';
import App from './App';

notifee.onBackgroundEvent(async ({ type, detail }) => {
  const { notification, pressAction } = detail;

  // Check if the user pressed the "Mark as read" action
  if (type === EventType.ACTION_PRESS && pressAction.id === 'mark-as-read') {
    // Update external API
    await fetch(`https://my-api.com/chat/${notification.data.chatId}/read`, {
      method: 'POST',
    });

    // Remove the notification
    await notifee.cancelNotification(notification.id);
  }
});

// Register main application
AppRegistry.registerComponent('app', () => App);
```

The handler callback expects that once the task has completed a Promise is returned/resolved. The above example makes use
of an [`async function`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) which
returns an implicit Promise once complete. If you are not using `async`, ensure your handler callback returns a promise
once complete.

> **iOS delivery events.** `DELIVERED` is emitted to `onForegroundEvent` for **all** Notify Kit-owned notifications presented while the app is in foreground — immediate `displayNotification` calls, trigger notifications that fire in foreground, and `handleFcmMessage` foreground displays. Trigger notifications that fire while the app is in background or killed do **not** emit `DELIVERED` on iOS (platform limitation — `willPresentNotification:` only fires in foreground and iOS provides no equivalent callback for background-presented local notifications). Android emits `DELIVERED` unconditionally in both cases. If you need delivery confirmation for background trigger notifications on iOS, query `getDisplayedNotifications()` after the app returns to foreground.

## App open events

If user interaction on a notification has caused your application to open, you may want to obtain the notification which triggered the app to open (e.g. a specific chat message). Call `getInitialNotification()` early in your React lifecycle to retrieve that notification.

> `getInitialNotification()` works on **both Android and iOS**. An iOS cold-start bug that caused it to return `null` even when the app was launched by a notification was fixed in v9.1.12. Apps that were migrating to the `PRESS` event via `onForegroundEvent` as a workaround can continue to do so — both patterns are supported and idiomatic.

It is recommended to always check if a notification has caused your app to open before displaying the main app content. Once consumed, the initial notification is removed.

For example, setup a "bootstrap" function inside of the root component of your application:

```jsx
import React, { useState, useEffect } from 'react';
import notifee from 'react-native-notify-kit';

function App() {
  const [loading, setLoading] = useState(true);

  // Bootstrap sequence function
  async function bootstrap() {
    const initialNotification = await notifee.getInitialNotification();

    if (initialNotification) {
      console.log('Notification caused application to open', initialNotification.notification);
      console.log('Press action used to open the app', initialNotification.pressAction);
    }
  }

  useEffect(() => {
    bootstrap()
      .then(() => setLoading(false))
      .catch(console.error);
  }, []);

  if (loading) {
    return null;
  }

  ...
}
```

If available, the `initialNotification` contains the notification & press action which triggered the app to open. Both
can be combined to perform logic inside of your application which the user expects from their interaction, for example,
opening a chat screen with a specific user who trigger the notification.

Once the initial notification has been consumed with a call to `getInitialNotification`, it is removed. If the app re-opens
before the initial notification has been consumed (e.g. the user manual closing & reopening), it will not be available.
