Building notification toasts with React
While there are no out-of-the-box toast components in the @knocklabs/react
library, it's easy to build toasts on top of the primitives exposed. In this guide, we'll show you just how to do that using the react-hot-toasts
library as our "toaster."
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 react-hot-toast
Adding the Knock providers
We'll need to wrap our toast producing component in a KnockProvider
and KnockFeedProvider
to set up a connection to Knock and connect to the authenticated user's feed. You can read more about the available props for the providers in the reference.
1import { KnockProvider, KnockFeedProvider } from "@knocklabs/react";
2
3// We'll write this next
4import NotificationToaster from "./NotificationToaster";
5
6const NotificationToastProducer = () => {
7 // An example of fetching the current authenticated user
8 const { user } = useCurrentUser();
9
10 return (
11 <KnockProvider apiKey={process.env.KNOCK_PUBLIC_API_KEY} userId={user.id}>
12 <KnockFeedProvider feedId={process.env.KNOCK_FEED_CHANNEL_ID}>
13 <NotificationToaster />
14 </KnockFeedProvider>
15 </KnockProvider>
16 );
17};
Rendering toasts when new notifications come in
Our KnockFeedProvider
exposes a useKnockFeed
hook, which will return a feedClient
we can use to bind to and receive real-time notifications being received on our feed.
1import toast, { Toaster } from "react-hot-toast";
2import { useEffect } from "react";
3import { useKnockFeed } from "@knocklabs/react";
4
5const NotificationToaster = () => {
6 const { feedClient } = useKnockFeed();
7
8 const onNotificationsReceived = ({ items }) => {
9 // Whenever we receive a new notification from our real-time stream, show a toast
10 // (note here that we can receive > 1 items in a batch)
11 items.forEach((notification) => {
12 //Use toast.custom to render the HTML content of the notification
13 toast.custom(
14 <div
15 dangerouslySetInnerHTML={{ __html: notification.blocks[0].rendered }}
16 ></div>,
17 { id: notification.id },
18 );
19 });
20
21 // Optionally, you may want to mark them as "seen" as well
22 feedClient.markAsSeen(items);
23 };
24
25 useEffect(() => {
26 // Receive all real-time notifications on our feed
27 feedClient.on("items.received.realtime", onNotificationsReceived);
28
29 // Cleanup
30 return () =>
31 feedClient.off("items.received.realtime", onNotificationsReceived);
32 }, [feedClient]);
33
34 return <Toaster />;
35};
36
37export default NotificationToaster;
Wrapping up
We can then test our workflow using the built-in test runner in Knock to produce messages, which will be received and displayed as a toast in your application.