Skip to content

Commit

Permalink
Merge pull request #696 from novuhq/inbox-react-hooks
Browse files Browse the repository at this point in the history
feat: inbox react hooks api reference
  • Loading branch information
LetItRock committed Sep 18, 2024
2 parents 5d5c968 + a325526 commit c858a18
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 66 deletions.
32 changes: 2 additions & 30 deletions inbox/headless/api-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,15 @@ sidebarTitle: 'API Reference'
---

import FunctionParams from '/snippets/inbox/headless/api-reference/function-params.mdx';
import NovuParams from '/snippets/inbox/headless/api-reference/novu-params.mdx';

## Novu

`Novu` is the primary class used to interact with the Novu API client, enabling you to fetch and manage notifications and preferences within your custom Inbox implementation.

### Constructor options

<ParamField path="applicationIdentifier" type="string" required>
`applicationIdentifier` is a unique identifier for the application. This is is
public credential that is used to authenticate the application with the Novu
API. `applicationIdentifier` can be copied from [API
Keys](https://dashboard.novu.co/api-keys) page.
</ParamField>

<ParamField path="subscriberId" type="string" required>
`subscriberId` is a unique identifier for the subscriber. Read more about
[subscribers](/concepts/subscribers).
</ParamField>

<ParamField path="subscriberHash" type="string">
`subscriberHash` is a unique identifier for the subscriber. It is used for
HMAC encryption. Read more about [HMAC
Encryption](/react/advanced-configuration#hmac-encryption).
</ParamField>

<ParamField path="backendUrl" type="string" default="https://api.novu.co">
Use `https://eu.api.novu.co` value for EU region.
</ParamField>

<ParamField path="socketUrl" type="string" default="https://ws.novu.co">
Use `https://eu.ws.novu.co` value for EU region.
</ParamField>

<ParamField path="useCache" type="boolean">
The field is used to enable/disable the cache for the notifications and
preferences. By default, the cache is enabled.
</ParamField>
<NovuParams />

### Usage
<Tabs>
Expand Down
17 changes: 17 additions & 0 deletions inbox/react/hooks/novu-provider.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: 'NovuProvider'
---

import NovuProviderExample from '/snippets/inbox/react/novu-provider-example.mdx';
import NovuParams from '/snippets/inbox/headless/api-reference/novu-params.mdx';

The `NovuProvider` is the top-level component that provides the [Novu instance](/inbox/headless/api-reference#novu) to the rest of the hooks through the context.
Usually, it's placed somewhere in the root of your application, which makes the hooks accessible throughout the application.

## `NovuProvider` props

<NovuParams />

## Example usage

<NovuProviderExample />
80 changes: 80 additions & 0 deletions inbox/react/hooks/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
title: 'Create Custom Inbox UI with React Hooks'
sidebarTitle: 'Overview'
---

import UseNotificationsExample from '/snippets/inbox/react/use-notifications-example.mdx';
import UseUnreadCountExample from '/snippets/inbox/react/use-unread-count-example.mdx';
import NovuProviderExample from '/snippets/inbox/react/novu-provider-example.mdx';

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:

<Steps>
<Step title="Install the @novu/react package">
```bash
npm install @novu/react
```
</Step>
<Step title="Implement the NovuProvider">
To implement the [NovuProvider](/inbox/react/hooks/novu-provider) component, you need to place it in your application's code at the tree level where you want the hooks to be accessible. Here's how you can do it:
<NovuProviderExample />
<Tip>
You can find the `applicationIdentifier` in the Novu Dashboard under the [API
keys page](https://dashboard.novu.co/api-keys). The `subscriberId` is the
unique identifier of the user in your application, learn more about
subscribers [here](/concepts/subscribers).
</Tip>

</Step>
<Step title="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.
```tsx
const YourCustomInbox = () => {
return (
<Popover.Root open={...} onOpenChange={...}>
<Popover.Trigger>
<BellButton />
</Popover.Trigger>
<Popover.Content>
<NotificationsList />
</Popover.Content>
</Popover.Root>
);
};
```

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

<UseUnreadCountExample />

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

<UseNotificationsExample />

The `NotificationItem` component renders each notification item.

When any action is performed on the `notification` instance for example "read" button is clicked,
the SDK will optimistically update notification that will result in the `useNotifications` hook rerender, so yo don't need to refetch and manually update your UI.
```tsx
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>
);
};
```
</Step>
</Steps>
56 changes: 56 additions & 0 deletions inbox/react/hooks/use-counts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: 'useCounts'
---

import UseUnreadCountExample from '/snippets/inbox/react/use-unread-count-example.mdx';

The `useCounts` hook is used to fetch the notification counts based on the provided filters.
You can use this hook to fetch the total count of unread, archived notifications or any other custom count based on the filters you provide.

The hook listens for changes in notification counts and will automatically refetch the counts whenever they are updated, for example, when a new notification is received.

### `useCounts` props

<ParamField path="filters" type="NotificationFilter[]">
Filters to be applied to notifications when calculating counts, allowing you
to filter notifications based on workflow tags, read status, and archived
status.
</ParamField>
<ParamField path="onSuccess" type="Function">
Callback function that will be called when the notification counts are
successfully fetched. In the callback argument, you will receive the fetched
counts.
</ParamField>
<ParamField path="onError" type="Function">
Callback function that will be called when there is an error fetching the
notification counts. In the callback argument, you will receive the error
object.
</ParamField>

### `useCounts` returns

<ParamField path="counts" type="Count[] | undefined">
An array of notification counts fetched by the hook. If there are no
notification counts fetched yet, it will be `undefined`.
</ParamField>
<ParamField path="isLoading" type="boolean">
A boolean value indicating the first fetch for notification counts is
in-flight.
</ParamField>
<ParamField path="isFetching" type="boolean">
A boolean value indicating whether the hook is fetching more notification
counts.
</ParamField>
<ParamField path="error" type="NovuError | undefined">
An error object that will be populated if there is an error fetching the
notification counts.
</ParamField>
<ParamField path="refetch" type="Function">
A function that can be called to refetch the notification counts.
</ParamField>

## Example usage

The below example demonstrates how to use the `useCounts` hook to fetch the unread notifications count.

<UseUnreadCountExample />
87 changes: 87 additions & 0 deletions inbox/react/hooks/use-notifications.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: 'useNotifications'
---

import UseNotificationsExample from '/snippets/inbox/react/use-notifications-example.mdx';

The `useNotifications` hook is a convenient way to fetch the list of notifications.
By default, it fetches both unread and read notifications, but you can apply [filters](/inbox/react/hooks/use-notifications#usenotifications-props) to retrieve only the relevant notifications for your specific use case.

The notifications fetched are paginated, and the hook provides a `fetchMore` function to load more notifications.
The fetched notifications are stored in the notifications array and are appended to the existing notifications as more are loaded.

Any action performed on a notification instance, like marking it as read, will optimistically update the notification, triggering a re-render in the hook and updating the notifications list accordingly, so you don't need to refetch and manually update your UI.

### `useNotifications` props

<ParamField path="tags" type="string[]">
Workflow tags can be used to filter notifications, and organize them into
different groups. Read more about how can you define [workflow
tags](/workflow/introduction#tags).
</ParamField>
<ParamField path="read" type="boolean">
Filter notifications based on their read status. If not provided, all
read/unread notifications will be returned.
</ParamField>
<ParamField path="archived" type="boolean">
Filter notifications based on their archived status. Archived notifications
are also read at the same time. If not provided, all archived/unarchived
notifications will be returned.
</ParamField>
<ParamField path="limit" type="number">
Limit the number of notifications to be fetched. It can take any number
between 1 and 100. Default is 10.
</ParamField>
<ParamField path="onSuccess" type="Function">
Callback function that will be called when the notifications are successfully
fetched. In the callback argument, you will receive the fetched notifications.
</ParamField>
<ParamField path="onError" type="Function">
Callback function that will be called when there is an error fetching the
notifications. In the callback argument, you will receive the error object.
</ParamField>

### `useNotifications` returns

<ParamField path="notifications" type="Notification[] | undefined">
An array of notifications fetched by the hook. If there are no notifications
fetched yet, it will be `undefined`.
</ParamField>
<ParamField path="isLoading" type="boolean">
A boolean value indicating the first fetch for notifications is in-flight.
</ParamField>
<ParamField path="isFetching" type="boolean">
A boolean value indicating whether the hook is fetching more notifications.
</ParamField>
<ParamField path="error" type="NovuError | undefined">
An error object that will be populated if there is an error fetching the
notifications.
</ParamField>
<ParamField path="hasMore" type="boolean">
A boolean value indicating whether there are more notifications available to
fetch.
</ParamField>
<ParamField path="fetchMore" type="Function">
A function that can be called to fetch more notifications. It will fetch the
next page of notifications and append them to the existing notifications.
</ParamField>
<ParamField path="refetch" type="Function">
A function that can be called to refetch the notifications. It will clear the
existing notifications and fetch the first page of notifications.
</ParamField>
<ParamField path="readAll" type="Function">
A function that can be called to mark all notifications as read, including
those that have not been fetched.
</ParamField>
<ParamField path="archiveAll" type="Function">
A function that can be called to archive all notifications, including those
that have not been fetched.
</ParamField>
<ParamField path="archiveAllRead" type="Function">
A function that can be called to archive all read notifications, including
those that have not been fetched.
</ParamField>

## Example usage

<UseNotificationsExample />
35 changes: 35 additions & 0 deletions inbox/react/hooks/use-novu.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: 'useNovu'
---

The `useNovu` hook is used to obtain the [Novu instance](/inbox/headless/api-reference#novu), which allows you to interact with the headless SDK interface.

### `useNovu` returns

The [Novu](/inbox/headless/api-reference#novu) class instance.

## Example usage

The below example demonstrates how to use the `useNovu` hook to listen for new notifications and show a toast notification.

```tsx
import { useNovu } from '@novu/react/hooks';

const NotificationToast = () => {
const novu = useNovu();

useEffect(() => {
const listener = ({ result: notification }) => {
// Show a toast notification
};

novu.on('notifications.notification_received', listener);

return () => {
novu.off('notifications.notification_received', listener);
};
}, [novu]);

return null;
};
```
62 changes: 62 additions & 0 deletions inbox/react/hooks/use-preferences.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: 'usePreferences'
---

The `usePreferences` hook is used to retrieve the subscriber preferences. The first item in the list will represent the subscriber global preferences,
while the remaining items will correspond to the preferences for each workflow.

The hook returns both critical and non-critical preferences. Critical preferences are those that are required for the subscriber to receive notifications,
while non-critical preferences are those that are optional and could be controlled by the subscriber. You can learn more about the preferences [here](/concepts/preferences).

By default the preferences are cached, but you can use the `refetch` function to fetch the latest preferences.

### `usePreferences` props

<ParamField path="onSuccess" type="Function">
Callback function that will be called when the subscriber preferences are
successfully fetched. In the callback argument, you will receive the fetched
preferences.
</ParamField>
<ParamField path="onError" type="Function">
Callback function that will be called when there is an error fetching the
subscriber preferences. In the callback argument, you will receive the error
object.
</ParamField>

### `usePreferences` returns

<ParamField path="preferences" type="Preference[] | undefined">
An array of subscriber preferences fetched by the hook. If there are no
preferences fetched yet, it will be `undefined`.
</ParamField>
<ParamField path="isLoading" type="boolean">
A boolean value indicating the first fetch for preferences is in-flight.
</ParamField>
<ParamField path="isFetching" type="boolean">
A boolean value indicating whether the hook is fetching more preferences.
</ParamField>
<ParamField path="error" type="NovuError | undefined">
An error object that will be populated if there is an error fetching the
preferences.
</ParamField>
<ParamField path="refetch" type="Function">
A function that can be called to refetch the preferences.
</ParamField>

## Example usage

```tsx
import { usePreferences } from '@novu/react/hooks';

const PreferencesList = () => {
const { preferences, isLoading, error, refetch } = usePreferences();

return (
<Show when={!isLoading} fallback={<PreferencesListSkeleton />}>
{preferences?.map((preference) => {
return <PreferenceItem key={preference.id} preference={preference} />;
})}
</Show>
);
};
```
Loading

0 comments on commit c858a18

Please sign in to comment.