Building custom notifications UI with React
Using our @knocklabs/react-notification-feed
and @knocklabs/client
libraries, you can create fully custom notification UIs that are backed by the Knock Feed API and Websockets to receive and process real-time notifications in your web application.
In this guide, we'll take a look at creating a completely custom notifications page in our application.
Getting started
To use this example, you'll need an account on Knock, as well as an in-app feed channel with a workflow that produces in-app feed messages. You'll also need:
- A public API key for the Knock environment (set as
KNOCK_PUBLIC_API_KEY
) - The channel ID for the in-app feed (set as
KNOCK_FEED_CHANNEL_ID
)
Installing dependencies
1npm install @knocklabs/react-notification-feed
KnockFeedProvider
Adding the We'll need to wrap our notifications page in a KnockFeedProvider
to setup a connection to Knock and connect to the authenticated user's feed. You can read more about the available props for the feed provider in the reference.
1import { KnockFeedProvider } from "@knocklabs/react-notification-feed";
2
3const NotificationsPage = () => {
4 const { user } = useCurrentUser();
5
6 return (
7 <KnockFeedProvider
8 apiKey={process.env.KNOCK_PUBLIC_API_KEY}
9 feedId={process.env.KNOCK_FEED_CHANNEL_ID}
10 userId={user.id}
11 >
12 <NotificationsList />
13 </KnockFeedProvider>
14 );
15};
Creating a custom notifications page
In our notifications page, we'll use the store exposed by the KnockFeedProvider
in order to render the list of notifications that ewe have available.
1const NotificationsList = () => {
2 const { useFeedStore } = useKnockFeed();
3 const items = useFeedStore((state) => state.items);
4
5 return (
6 <div className="notifications">
7 {items.map((item) => (
8 <NotificationCell key={item.id} item={item} />
9 ))}
10 </div>
11 );
12};
Creating a notification cell
We'll want to render a notification cell for every notification in our feed. Lets wrap that behavior up in a component for easy reuse:
1type Props = {
2 item: FeedItem,
3};
4
5const NotificationCell: React.FC<Props> = ({ item }) => {
6 // Group the content blocks by the name for easy lookup
7 const blocksByName = useMemo(() => {
8 return item.blocks.reduce((acc, block) => {
9 return { ...acc, [block.name]: block };
10 }, {});
11 }, [item]);
12
13 const maybeActor = item.actors[0];
14
15 return (
16 <div className="notification-cell">
17 {maybeActor && (
18 <span class="notification-cell__actor">{maybeActor.name}</span>
19 )}
20
21 {blocksByName.body && (
22 <div
23 className="notification-cell__content"
24 dangerouslySetInnerHTML={{ __html: blocksByName.body.rendered }}
25 />
26 )}
27 </div>
28 );
29};
Wrapping up
There's a lot more we can do with our notifications page, but we'll leave that as an exercise to the reader. Here are some examples:
- Adding mark as read, and archiving behavior to the notification cell
- Displaying a count of the total number of notifications
Check out the feed guide in the @knocklabs/client
reference to learn about the available methods.