Prebuilt Inbox Component

This guide covers the prebuilt Notification Inbox components for an Indie Notification Inbox.

native-notify ships a prebuilt Notification Inbox: a bell icon for your app header with an unread dot, and a full-screen inbox screen that opens when the bell is tapped. In mode="indie" the inbox displays the current user's notifications — the same data returned by the getIndieNotificationInbox function.

Quick start

Add the <NotificationInboxBell> component to your header with mode="indie" and the user's subId:

import { NotificationInboxBell } from 'native-notify';

// Expo Router / React Navigation header:
<Stack.Screen
  name="index"
  options={{
    headerRight: () => (
      <NotificationInboxBell
        appId={yourAppId}
        appToken="yourAppToken"
        mode="indie"           // or "mass" (default)
        subId={currentUser.id} // required when mode="indie"
      />
    ),
  }}
/>

The subId is the unique user ID you registered with Native Notify during the Indie Push Notification registration process — the component uses it to fetch that user's inbox.

appId and appToken are optional on every inbox component when you set them once with NativeNotify.init() or <NativeNotifyProvider> — pass them explicitly only if you prefer.

Indie mode notes

  • Per-row delete is available. Each row shows a delete button that removes only that user's notification using the deleteIndieNotificationInbox function. The row is removed optimistically and is restored if the delete request fails.
  • Hide the delete button by passing allowDelete={false}.
  • Works in Expo Go, on simulators, and on web. Read state is tracked per user (subId), so the unread dot works everywhere — unlike mass mode, which needs a real device for its push token.
  • Opening the inbox marks the fetched notifications as read, so the unread dot clears when the inbox opens.
  • The app icon badge follows the unread count — whenever the unread count refreshes, it is synced to the app icon badge with Notifications.setBadgeCountAsync(). Pass syncBadge={false} to opt out.

Props

NotificationInboxBell accepts the following props:

PropTypeDefaultDescription
appIdnumber | stringYour Native Notify App ID.
appTokenstringYour Native Notify App Token.
mode'mass' | 'indie''mass'Set to 'indie' for per-user notifications.
subIdnumber | stringRequired when mode="indie" (the user's unique ID).
takenumber20Number of notifications fetched per page.
syncBadgebooleantrueSync the unread count to the app icon badge.
colorsobjectlight/dark themePartial theme override — see Colors.
titlestring'Notifications'Inbox header title.
emptyTextstring"You're all caught up"Empty-state body text.
allowDeletebooleantrueShow the per-row delete button (indie mode only). Pass false to hide it.
onNotificationPress(notification) => voidCalled when a row is tapped.
onOpen() => voidIf set, called instead of opening the built-in inbox screen.
showCountbooleanfalseShow a numeric unread badge instead of a plain dot.
maxCountnumber99Badge cap — shows "99+" past it.
renderIcon({ unreadCount, color }) => nodebundled bell iconCustom bell icon.
iconSizenumber24Bell icon size.
iconStyleStyleProp<ImageStyle>Style override for the bell icon.
containerStyleStyleProp<ViewStyle>Style override for the bell container.

Colors

Colors follow the device's light/dark mode automatically. Pass any subset of the keys below in colors to override the theme:

<NotificationInboxBell
  appId={yourAppId}
  appToken="yourAppToken"
  mode="indie"
  subId={currentUser.id}
  colors={{ dot: '#EF4444', accent: '#2563EB' }}
/>
  • icon, dot, badgeText
  • background, headerBackground, card, border
  • title, text, mutedText, emptyTitle, emptyText
  • accent, delete

Custom screen and headless hook

Want your own trigger instead of the bell? Render <NotificationInboxScreen> and control the modal yourself with visible / onClose — it accepts all of the props above plus these:

PropTypeDefaultDescription
visiblebooleanWhether the inbox modal is shown.
onClose() => voidCalled when the modal is dismissed.

To build a fully custom UI, use the headless hook:

import { useNotificationInbox } from 'native-notify';

const {
  notifications,   // fetched inbox rows
  unreadCount,     // unread count for your own badge
  loading,         // initial load in progress
  refreshing,      // pull-to-refresh in progress
  loadingMore,     // next page in progress
  hasMore,         // more pages available
  error,           // error message, if any
  openInbox,       // marks fetched notifications as read
  refresh,
  refreshUnread,
  loadMore,
  deleteNotification, // per-row delete (indie mode)
} = useNotificationInbox({
  appId: yourAppId,
  appToken: 'yourAppToken',
  mode: 'indie',
  subId: currentUser.id, // required when mode: 'indie'
  take: 20,
  syncBadge: true, // sync the unread count to the app icon badge
});

Exact pagination is available for custom UIs: getIndieNotificationInboxPage() returns { rows, total } — the server's X-Total-Count — so "load more" is exact instead of a guess.

Inbox row data

Each row in the inbox is shaped like this:

{
  notification_id, // unique notification ID — used for deletes
  date,            // notification date
  title,           // notification title
  message,         // notification message
  pushData,        // data object sent with the push notification
}