docs/platform/subscription/headless-hooks.mdx
Novu @novu/react package provides Subscription hooks that let you build your own custom subscription experiences from scratch.
These hooks allow you to list, create, update, and delete subscriptions while leveraging Novu's state management.
<Note> Hooks are available in [`@novu/nextjs`](/platform/sdks/react), [`@novu/react-native`](/platform/sdks/react-native), [`@novu/react`](/platform/sdks/react). For a complete reference on all available Subscription endpoints, refer to the [API reference documentation](/platform/sdks/react/hooks/subscription). </Note>The useSubscriptions hook retrieves all subscriptions associated with a specific topic for the current subscriber. This is useful for rendering a list of "My Subscriptions," where subscribers can view all the subscriptions they've subscribed to.
The subscriptions array contains TopicSubscription objects. You can refer to the TopicSubscription interface for the full type definition.
import { useSubscriptions } from '@novu/react';
function SubscriptionList() {
const { subscriptions, isLoading } = useSubscriptions({
topicKey: 'product-updates'
});
if (isLoading) return <div>Loading...</div>;
return (
<ul>
{subscriptions.map((subscription) => (
<li key={subscription.id}>
<h3>{subscription.name}</h3>
+
</li>
))}
</ul>
);
}
If you need to manage a specific subscription instance, then use the useSubscription hook. This hook fetches the details and preferences for a single subscription.
import { useSubscription } from '@novu/react';
function ProjectSettings() {
const { subscription, isLoading } = useSubscription({
topicKey: 'project-123',
identifier: 'user-project-alert'
});
if (isLoading) return <div>Loading...</div>;
if (!subscription) return <div>You are not subscribed to this project.</div>;
return (
<div>
<h3>{subscription.name}</h3>
</div>
);
}
To allow users to opt-in to a topic, use the useCreateSubscription hook. This is often used on "Follow" or "Subscribe" buttons.
import { useCreateSubscription } from '@novu/react';
function SubscribeButton() {
const { create, isCreating } = useCreateSubscription();
const handleSubscribe = async () => {
const { data, error } = await create({
topicKey: 'project-123',
identifier: 'user-project-alert',
// Optional: Set initial preferences
preferences: []
});
if (error) {
console.error('Failed to subscribe', error);
return;
}
console.log('Subscribed successfully!', data);
};
return (
<button onClick={handleSubscribe} disabled={isCreating}>
{isCreating ? 'Subscribing...' : 'Subscribe to Updates'}
</button>
);
}
Use useUpdateSubscription to modify an existing subscription. This is primarily used to toggle workflow preferences, enabling, or disabling specific notifications within the subscription.
import { useUpdateSubscription } from '@novu/react';
function PreferenceToggle({ identifier, preferences, name, topicKey }) {
const { update, isUpdating } = useUpdateSubscription();
const savePreferences = async () => {
await update({
topicKey,
identifier,
name,
preferences,
});
};
return (
<button onClick={savePreferences} disabled={isUpdating}>
Save preferences
</button>
);
}
If you need to update a single preference, use the dedicated helpers available on the subscription object, such as:
subscription.updatePreference(...), orsubscription.preferences and calling preference.update(...)import { useSubscription } from '@novu/react';
function PreferenceList() {
const { subscription } = useSubscription({
topicKey: 'project-123',
identifier: 'user-project-alert'
});
if (!subscription) return null;
return (
<div>
{subscription.preferences.map((preference) => (
<div key={preference.workflowId}>
<label>{preference.label}</label>
<input
type="checkbox"
checked={preference.enabled}
// Update the preference directly using the instance method
onChange={(e) => preference.update({ value: e.target.checked })}
/>
</div>
))}
</div>
);
}
To allow users to opt out or unsubscribe, use the useRemoveSubscription hook.
import { useRemoveSubscription } from '@novu/react';
function UnsubscribeButton({ identifier: string, topicKey: string }) {
const { remove, isRemoving } = useRemoveSubscription();
const handleUnsubscribe = async () => {
await remove({
identifier,
topicKey,
});
};
return (
<button onClick={handleUnsubscribe} disabled={isRemoving}>
{isRemoving ? 'Removing...' : 'Unsubscribe'}
</button>
);
}