A high-performance React Native remote push notification library built on NitroModules.
Platform support: iOS only. Android support is not yet implemented.
pnpm add react-native-nitro-notification
npx pod-installThe library needs to receive the APNs device token from your app delegate. Add the following to your AppDelegate:
import NitroNotification
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
NotificationCenter.default.post(
name: NitroNotificationTokenNotification,
object: nil,
userInfo: [NitroNotificationTokenKey: deviceToken]
)
}No other app delegate changes are required. The library registers itself as a UNUserNotificationCenterDelegate automatically at load time.
import { Notifications } from 'react-native-nitro-notification';
const status = await Notifications.requestPermissions({
alert: true,
sound: true,
badge: true,
});
// status: 'granted' | 'denied' | 'undetermined' | 'provisional'const status = await Notifications.getPermissionStatus();requestPermissions automatically registers for remote notifications on success, so the token is available immediately after a 'granted' or 'provisional' result.
const token = await Notifications.getDevicePushToken();await Notifications.unregisterForNotifications();// Token refreshed
const sub = Notifications.addOnTokenRefreshed((token) => {
console.log('New token:', token);
});
// Notification tapped
const sub = Notifications.addOnNotificationTapped((response) => {
console.log('Tapped:', response.notification.title);
console.log('Action:', response.actionIdentifier);
});
// Clean up
sub.remove();addOnNotificationTapped only fires for listeners that exist when the tap arrives. When a tap launches the app from a killed state, your JS listener is not registered yet, so the event is lost. The library keeps the most recent tap natively so you can read it on startup:
// Run once the navigation is ready
const response = Notifications.getLastNotificationResponse();
if (response) {
navigateTo(response);
Notifications.clearLastNotificationResponse();
}Only the most recent tap is stored. Call clearLastNotificationResponse after handling it, otherwise the same tap is returned again the next time you read it (for example after a JS reload).
On Android, getLastNotificationResponse currently always returns undefined.
By default, foreground notifications are presented with alert, badge, and sound. Use setNotificationHandler to control presentation per notification:
Notifications.setNotificationHandler(async (notification) => {
console.log('Received in foreground:', notification.title);
return { alert: true, badge: true, sound: false };
});
// Clear the handler
Notifications.setNotificationHandler(undefined);The handler has a default timeout of 5000 ms. If it rejects or times out, the notification falls back to showing alert, badge, and sound.
// Custom timeout
Notifications.setNotificationHandler(async (notification) => {
return { alert: true, badge: false, sound: true };
}, 3000);Register categories to attach action buttons (and inline text replies) to notifications. A notification uses a category when its push payload has a matching categoryIdentifier.
await Notifications.setNotificationCategories([
{
identifier: 'message',
actions: [
{
identifier: 'reply',
buttonTitle: 'Reply',
textInput: { submitButtonTitle: 'Send', placeholder: 'Write a reply' },
},
{
identifier: 'delete',
buttonTitle: 'Delete',
options: { isDestructive: true, opensAppToForeground: false },
},
],
},
]);
Notifications.addOnNotificationTapped((response) => {
if (response.actionIdentifier === 'reply') {
console.log('Reply text:', response.userText);
}
});setNotificationCategories replaces the full set of registered categories. Calling it again removes any category that is not in the new array, so always pass every category your app needs.
On Android this method currently rejects with an UnsupportedOperationException.
| Method | Description |
|---|---|
requestPermissions(options?) |
Prompts the user for notification permissions. Returns the resulting PermissionStatus. On success, also calls registerForRemoteNotifications() so the push token is immediately available. |
getPermissionStatus() |
Returns the current PermissionStatus without prompting. |
getDevicePushToken() |
Registers for remote notifications and resolves with the APNs device token as a hex string. |
unregisterForNotifications() |
Unregisters from remote notifications on the device. |
setNotificationHandler(handler, timeoutMs?) |
Sets a callback invoked when a notification arrives while the app is in the foreground. The handler returns NotificationPresentationOptions to control how the notification is shown. Pass undefined to clear the handler. |
setNotificationCategories(categories) |
Registers the notification categories and their actions. Replaces all previously registered categories. Rejects on Android. |
addOnTokenRefreshed(listener) |
Subscribes to push token refresh events. Returns a ListenerSubscription. |
addOnNotificationTapped(listener) |
Subscribes to notification tap events. Returns a ListenerSubscription. |
getLastNotificationResponse() |
Synchronously returns the most recent NotificationResponse, or undefined if there is none. Use it on startup to recover a tap that launched the app from a killed state. Always undefined on Android. |
clearLastNotificationResponse() |
Clears the stored response so it is not returned again. |
| Value | Description |
|---|---|
'granted' |
The user has authorized notifications. |
'denied' |
The user has denied notifications. |
'undetermined' |
The user has not yet been asked. |
'provisional' |
Provisional authorization (iOS) -- notifications deliver silently to Notification Center without a prompt. |
All fields are iOS-specific. On Android, this object is accepted but ignored.
| Property | Type | Default | Description |
|---|---|---|---|
alert |
boolean? |
true |
Show notification banners and Notification Center entries. |
sound |
boolean? |
true |
Play a sound when a notification is delivered. |
badge |
boolean? |
true |
Update the app icon badge number. |
carPlay |
boolean? |
false |
Display notifications in CarPlay. |
criticalAlert |
boolean? |
false |
Play sound even when muted or Do Not Disturb is on. Requires an Apple entitlement. |
providesAppNotificationSettings |
boolean? |
false |
Show a link to your in-app notification settings from the system settings page. |
provisional |
boolean? |
false |
Request provisional authorization -- no prompt shown to the user. |
| Property | Type | Description |
|---|---|---|
title |
string? |
Notification title. |
body |
string? |
Notification body. |
data |
Record<string, string>? |
Custom key-value payload. |
badge |
number? |
Badge count included in the payload. |
Received in addOnNotificationTapped callbacks and returned by getLastNotificationResponse.
| Property | Type | Description |
|---|---|---|
notification |
NotificationPayload |
The notification that was tapped. |
actionIdentifier |
string |
The identifier of the action that was invoked (e.g. UNNotificationDefaultActionIdentifier for a plain tap). |
userText |
string? |
Text typed by the user when the action has a textInput. Undefined otherwise or when the field is empty. |
| Property | Type | Description |
|---|---|---|
identifier |
string |
Matches the categoryIdentifier field in the push payload. |
actions |
NotificationAction[] |
Actions shown on notifications of this category. |
options |
NotificationCategoryOptions? |
iOS-specific category options. |
All fields are iOS only.
| Property | Type | Description |
|---|---|---|
previewPlaceholder |
string? |
Body placeholder shown when the user has hidden previews. |
intentIdentifiers |
string[]? |
Siri intent class identifiers associated with the category. |
categorySummaryFormat |
string? |
Format string for the grouped notification summary. |
customDismissAction |
boolean? |
Notify the app when the user explicitly dismisses the notification. |
allowInCarPlay |
boolean? |
Allow the actions to appear in CarPlay. |
showTitle |
boolean? |
Show the title even when the user has hidden previews. |
showSubtitle |
boolean? |
Show the subtitle even when the user has hidden previews. |
| Property | Type | Description |
|---|---|---|
identifier |
string |
Delivered back in NotificationResponse.actionIdentifier. |
buttonTitle |
string |
Label shown on the action button. |
textInput |
NotificationTextInput? |
When present, the action becomes an inline text reply field. |
options |
NotificationActionOptions? |
Action behavior options. |
| Property | Type | Default | Description |
|---|---|---|---|
isDestructive |
boolean? |
false |
Render the button in a destructive style. iOS only. |
isAuthenticationRequired |
boolean? |
false |
Require device authentication before the action fires. iOS only. |
opensAppToForeground |
boolean? |
true |
Bring the app to the foreground when the action is triggered. |
| Property | Type | Description |
|---|---|---|
submitButtonTitle |
string |
Title of the submit button. iOS only. |
placeholder |
string |
Placeholder shown before the user starts typing. |
Returned by the NotificationHandler to control foreground presentation.
| Property | Type | Description |
|---|---|---|
alert |
boolean |
Show the notification banner. |
badge |
boolean |
Update the app icon badge. |
sound |
boolean |
Play the notification sound. |
type NotificationHandler = (notification: NotificationPayload) => Promise<NotificationPresentationOptions>;interface ListenerSubscription {
remove: () => void;
}MIT