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(). PasssyncBadge={false}to opt out.
Props
NotificationInboxBell accepts the following props:
| Prop | Type | Default | Description |
|---|---|---|---|
appId | number | string | — | Your Native Notify App ID. |
appToken | string | — | Your Native Notify App Token. |
mode | 'mass' | 'indie' | 'mass' | Set to 'indie' for per-user notifications. |
subId | number | string | — | Required when mode="indie" (the user's unique ID). |
take | number | 20 | Number of notifications fetched per page. |
syncBadge | boolean | true | Sync the unread count to the app icon badge. |
colors | object | light/dark theme | Partial theme override — see Colors. |
title | string | 'Notifications' | Inbox header title. |
emptyText | string | "You're all caught up" | Empty-state body text. |
allowDelete | boolean | true | Show the per-row delete button (indie mode only). Pass false to hide it. |
onNotificationPress | (notification) => void | — | Called when a row is tapped. |
onOpen | () => void | — | If set, called instead of opening the built-in inbox screen. |
showCount | boolean | false | Show a numeric unread badge instead of a plain dot. |
maxCount | number | 99 | Badge cap — shows "99+" past it. |
renderIcon | ({ unreadCount, color }) => node | bundled bell icon | Custom bell icon. |
iconSize | number | 24 | Bell icon size. |
iconStyle | StyleProp<ImageStyle> | — | Style override for the bell icon. |
containerStyle | StyleProp<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,badgeTextbackground,headerBackground,card,bordertitle,text,mutedText,emptyTitle,emptyTextaccent,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:
| Prop | Type | Default | Description |
|---|---|---|---|
visible | boolean | — | Whether the inbox modal is shown. |
onClose | () => void | — | Called 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
}