Building custom notifications UI with hooks (headless)
Using our @knocklabs/react-native
library, you can create fully custom notification UIs that are backed by the Knock Feed API and real-time service.
In this guide, you'll find common recipes to help you build in-app feed experiences within your React Native applications in a headless way using the Knock hooks. The SDK handles all aspects of managing the data surrounding notifications on your behalf, including managing unread badge counts.
Quick links:
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
1
npm install @knocklabs/react-native
When using React Native with Expo, install our Expo SDK instead:
1
npm install @knocklabs/expo
Rendering a notification feed
userToken
as a prop to the KnockFeedProvider
component. For more information, visit the security & authentication guide for client-side applications.KnockProvider
and KnockFeedProvider
Using the 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
import { useEffect } from "react"; import { KnockProvider, KnockFeedProvider, useKnockFeed } from "@knocklabs/react-native"; const YourApp = () => { const currentUser = useCurrentUser(); return ( <KnockProvider apiKey={process.env.KNOCK_PUBLIC_API_KEY} userId={currentUser.id} // In production, you must pass a signed userToken // and enable enhanced security mode in your Knock dashboard // userToken={currentUser.knockUserToken} > <KnockFeedProvider feedId={process.env.KNOCK_FEED_CHANNEL_ID}> <NotificationFeed /> </KnockFeedProvider> </KnockProvider> ); }; const NotificationFeed = () => { const { useFeedStore, feedClient } = useKnockFeed(); const { items, metadata } = useFeedStore(); // Fetch the feed useEffect(() => feedClient.fetch(), [feedClient]); return ( <View> <Text>Total unread: {metadata.unread_count}</Text> {items.map(item => ( <View key={item.id}> {/* Notification cell goes here */} </View> )} </View> ) };
useNotifications
hook
Using the 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
import { useAuthenticatedKnockClient, useNotifications, useNotificationStore } from "@knocklabs/react-native"; const MyNotificationsFeed = () => { const knock = useAuthenticatedKnockClient( process.env.KNOCK_PUBLIC_API_KEY, user.id, user.knockToken, ); const notificationFeed = useNotifications( knock, process.env.KNOCK_FEED_CHANNEL_ID, ); const { metadata, items } = useNotificationStore(notificationFeed); // Fetch the feed contents useEffect(() => { notificationFeed.fetch(); }, [notificationFeed]); return ( <View> <Text>Total unread: {metadata.unread_count}</Text> {items.map(item => ( <View key={item.id}> {/* Notification cell goes here */} </View> )} </View> ); };
Common feed recipes
Filtering/scoping a feed
A feed can be scoped by any of the parameters that are accepted on the feed endpoint via the FeedClientOptions
set in the defaultFeedOptions
for the KnockFeedProvider
component, or via the useNotifications
hook.
You can read more in this guide on feed filtering.