Create Custom Inbox UI with React Hooks

Learn how to build a custom notifications UI using React hooks powered by Novu

The @novu/react package offers an interface that enables you to build a custom notifications UI using React hooks that are powered by real-time data from the Novu services.

These hooks are designed for use in both mobile and web applications, offering a flexible approach to building a custom notifications UI tailored to your application's requirements.

Getting Started

Follow these steps to get started with building your custom inbox UI:

Install the @novu/react package
npm install @novu/react 
Implement the NovuProvider

To implement the NovuProvider component, you need to place it in your application's code at the tree level where you want the hooks to be accessible.

import { NovuProvider } from '@novu/react';
 
function App() {
  return (
    <NovuProvider
      subscriberId="SUBSCRIBER_ID"
      applicationIdentifier="APPLICATION_IDENTIFIER"
    >
      {/* Your app components */}
    </NovuProvider>
  );
}

You can find the applicationIdentifier in the Novu Dashboard under the API keys page. The subscriberId is the unique identifier of the user in your application, learn more about subscribers here.

Create the custom Inbox UI

For example, you can create a custom popover UI with a bell icon that shows the unread notifications count and a list of notifications.

const YourCustomInbox = () => {
  return (
    <Popover.Root open={...} onOpenChange={...}>
      <Popover.Trigger>
        <BellButton />
      </Popover.Trigger>
      <Popover.Content>
        <NotificationsList />
      </Popover.Content>
    </Popover.Root>
  );
};

Bell Button with Unread Count

The BellButton component fetches the unread notifications count and renders the count value in the indicator:

import { useUnreadCount } from '@novu/react';
 
function BellButton() {
  const { unreadCount, isLoading, error } = useUnreadCount();
 
  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
 
  return (
    <button>
      <BellIcon />
      {unreadCount > 0 && <span className="badge">{unreadCount}</span>}
    </button>
  );
}

Notifications List

The NotificationsList component retrieves and displays the notifications list with infinite scrolling functionality:

import { useNotifications } from '@novu/react';
 
function NotificationsList() {
  const {
    notifications,
    isLoading,
    hasMore,
    loadMore,
    error
  } = useNotifications();
 
  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
 
  return (
    <div>
      {notifications.map((notification) => (
        <NotificationItem
          key={notification.id}
          notification={notification}
        />
      ))}
      {hasMore && (
        <button onClick={loadMore}>Load More</button>
      )}
    </div>
  );
}

Notification Item

The NotificationItem component renders each notification item. When any action is performed on the notification instance (e.g., "read" button is clicked), the SDK will optimistically update the notification, which will trigger a rerender of the useNotifications hook.

const NotificationItem = ({ notification }) => {
  return (
    <div>
      {notification.isRead && <span className="dot-indicator" />}
      <h3>{notification.subject}</h3>
      <p>{notification.body}</p>
      <button onClick={() => notification.read()}>Read</button>
      <button onClick={() => notification.archive()}>Archive</button>
    </div>
  );
};

Learn more about the Hook interfaces in the React SDK documentation.

On this page