@novu/headless: headlessService.fetchNotifications({onSuccess}) constantly receives latest state

Let me refine if we have an expected behaviour of fetchNotifications With code below we have onSuccess invoked on every notifications update, it looks like socket used there, but there is no direct reference to it in the documentation. You can also notice that we have this line of code listenNotificationReceiveChange(() => {}) - it's exactly the part that makes onSuccess handler invoked (as headlessService?.fetchNotifications option) Is this a behaviour we can rely on or it's kind of a bug? Is there any other way to get constant updates of the notifications with their latest state?
const fetchNotifications = async (onPushNotifications: OnPushNotificationsHandler) => {
if (!sessionInitialized) {
throw new Error('Session is not initialized')
}

headlessService?.fetchNotifications({
listener: () => {},
onSuccess: (response: IPaginatedResponse<IMessage>) => {
const { data } = response
const notifications = unifyNotifications(data)
onPushNotifications(notifications)
},
onError: (error) => {
// eslint-disable-next-line no-console
console.error('Failed to fetch notifications:', error)
},
query: { read: false },
page: 0,
})
}


initializeSession(userId, config.NovuIdentifier, novuSignature.toLocaleLowerCase())
.then(() => {
fetchNotifications(onPushNotifications)
listenNotificationReceiveChange(() => {})
return null
})
.catch((error: Error) => {
console.error('Failed to initialize session:', error)
})
const fetchNotifications = async (onPushNotifications: OnPushNotificationsHandler) => {
if (!sessionInitialized) {
throw new Error('Session is not initialized')
}

headlessService?.fetchNotifications({
listener: () => {},
onSuccess: (response: IPaginatedResponse<IMessage>) => {
const { data } = response
const notifications = unifyNotifications(data)
onPushNotifications(notifications)
},
onError: (error) => {
// eslint-disable-next-line no-console
console.error('Failed to fetch notifications:', error)
},
query: { read: false },
page: 0,
})
}


initializeSession(userId, config.NovuIdentifier, novuSignature.toLocaleLowerCase())
.then(() => {
fetchNotifications(onPushNotifications)
listenNotificationReceiveChange(() => {})
return null
})
.catch((error: Error) => {
console.error('Failed to initialize session:', error)
})
7 Replies
Ask Inkeep
Ask Inkeep•6mo ago
Hi @viktor.mozharovskiy, I'm an AI assistant for Novu. While a team member reviews this question, I'll see if I can find relevant sources for your question. ----------------------------- While I generate an answer, here are some sources that might be helpful: * Headless API Reference * Get Started * API Reference * How to use Headless Notification Center ----------------------------- Answer The behavior you're describing with fetchNotifications being invoked on every notification update is not explicitly documented in the provided information sources. (1) The documentation mainly describes fetchNotifications as a method to fetch notifications, but doesn't mention real-time updates. However, the listenNotificationReceiveChange method you're using is likely related to real-time updates. (2) The Novu library provides real-time socket APIs for getting updates about new notifications added to the user's feed. For constant updates of notifications with their latest state, the documentation suggests using the useSocket hook:
import { NovuProvider, useSocket } from "@novu/notification-center";

function Novu() {
return (
<NovuProvider
subscriberId={"SUBSCRIBER_ID"}
applicationIdentifier={"APPLICATION_IDENTIFIER"}
>
<CustomNotificationCenter />
</NovuProvider>
);
}

function CustomNotificationCenter() {
useSocket({
onSocketDisconnected: () => {
console.log('Socket disconnected');
},
onSocketReconnected: () => {
console.log('Socket reconnected');
},
onUnseenCountChanged: (unseenCount: number) => {
console.log('New unseen count', unseenCount);
},
onNotificationClick: (message: IMessage) => {
console.log('Notification clicked', message);
},
});

return <div>Custom notification center</div>;
}
import { NovuProvider, useSocket } from "@novu/notification-center";

function Novu() {
return (
<NovuProvider
subscriberId={"SUBSCRIBER_ID"}
applicationIdentifier={"APPLICATION_IDENTIFIER"}
>
<CustomNotificationCenter />
</NovuProvider>
);
}

function CustomNotificationCenter() {
useSocket({
onSocketDisconnected: () => {
console.log('Socket disconnected');
},
onSocketReconnected: () => {
console.log('Socket reconnected');
},
onUnseenCountChanged: (unseenCount: number) => {
console.log('New unseen count', unseenCount);
},
onNotificationClick: (message: IMessage) => {
console.log('Notification clicked', message);
},
});

return <div>Custom notification center</div>;
}
Ask Inkeep
Ask Inkeep•6mo ago
This approach uses the useSocket hook to listen for various events, including changes in unseen count and notification clicks. Regarding whether the behavior you're experiencing is a bug or a feature you can rely on, I don't have enough information from the official documentation to make a definitive statement. (3) (1) (4) (2) It would be best to verify this behavior with the Novu team directly or check for any recent updates in the official documentation.
Ask Inkeep
Ask Inkeep•6mo ago
Feel free to tag @Ask Inkeep with additional questions. Got it. Tagging @Support for additional help.
Pawan Jain
Pawan Jain•6mo ago
@viktor.mozharovskiy Could you share the codesnippet for listenNotificationReceiveChange method as well?
viktor.mozharovskiy
viktor.mozharovskiyOP•6mo ago
sure
const listenNotificationReceiveChange = async (
onPushNotification: (notification: NovuAppNotification | null) => void,
) => {
if (!sessionInitialized) {
throw new Error('Session is not initialized')
}

headlessService?.listenNotificationReceive({
listener: (response: IMessage) => {
const notifications = parseNovuNotification(response)
onPushNotification(notifications)
},
})
}
const listenNotificationReceiveChange = async (
onPushNotification: (notification: NovuAppNotification | null) => void,
) => {
if (!sessionInitialized) {
throw new Error('Session is not initialized')
}

headlessService?.listenNotificationReceive({
listener: (response: IMessage) => {
const notifications = parseNovuNotification(response)
onPushNotification(notifications)
},
})
}
but in the recent version of our codebase we don't use onPushNotification callback, so the usage looks the following (we just pass () => {}) : ``` initializeSession(userId, config.NovuIdentifier, novuSignature.toLocaleLowerCase()) .then(() => { fetchNotifications(onPushNotifications) listenNotificationReceiveChange(() => {}) return null }) @Pawan Jain did you have a chance to look through the above? It would be very helpful for us to hear your thought on it, then we will be able to move forward with this in our project. Thanks
Novu_Bot
Novu_Bot•6mo ago
@viktor.mozharovskiy, you just advanced to level 1!
viktor.mozharovskiy
viktor.mozharovskiyOP•6mo ago
@Pawan Jain , hopefully our message didn't dissolve among others 🙂 Your answer is highly awaited by our team. Thank you for your time and support!
Want results from more Discord servers?
Add your server