Headless hooks

Build a fully custom Subscription interface using hooks.

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.

Hooks are available in @novu/nextjs, @novu/react-native, @novu/react. For a complete reference on all available Subscription endpoints, refer to the API reference documentation.

Get all subscriptions

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 content they've opted into.

The subscriptions array contains TopicSubscription objects. You can refer to the TopicSubscription interface in the @novu/js package 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>
+         {/* Render your custom subscription UI here */}
        </li>
      ))}
    </ul>
  );
}

Get a single subscription

If you need to manage a specific subscription instance, then use the useSubscription hook. This hook fetches the details and preference states 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>
       {/* Render preferences or other subscription details */}
    </div>
  );
}

Create a subscription

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>
  );
}

Update a subscription

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({ subscriptionId, workflowId, }) {
  const { update, isUpdating } = useUpdateSubscription();
 
  const savePreferences = async () => {
    await update({
      topicKey: 'project-123',
      subscriptionId: subscriptionId,
      preferences,
    });
  };
 
  return (
    <button onClick={savePreferences} disabled={isUpdating}>
      Save preferences
    </button>
  );
}

Update a single preference

If you need to update a single preference, use the dedicated helpers available on the subscription object, such as:

  • subscription.updatePreference(...), or
  • mapping over subscription.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>
  );
}

Delete a subscription

To allow users to opt out or unsubscribe, use the useRemoveSubscription hook.

import { useRemoveSubscription } from '@novu/react';
 
function UnsubscribeButton({ subscriptionId }) {
  const { remove, isRemoving } = useRemoveSubscription();
 
  const handleUnsubscribe = async () => {
    await remove({ 
      subscriptionId: subscriptionId,
      topicKey: 'project-123'
    });
  };
 
  return (
    <button onClick={handleUnsubscribe} disabled={isRemoving}>
      {isRemoving ? 'Removing...' : 'Unsubscribe'}
    </button>
  );
}

On this page

Edit this page on GitHub