Building notification toasts with React

How to build notification toasts powered by Knock and 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."

See a live demo

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)
🌠
Find your channel ID. To find the channel ID for your in-app channel(s), go to Integrations > Channels in the Knock dashboard, navigate to the channel page of your in-app channel, and copy the channel ID.

Installing dependencies

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.