useSubscription
The useSubscription hook provides a straightforward way to subscribe to real-time events from the payment service. It manages the WebSocket connection lifecycle, allowing your components to react instantly to backend events like invoice.paid or subscription.updated.
This is essential for creating dynamic user experiences where the UI needs to reflect changes without requiring manual refreshes.
How It Works#
The hook abstracts the complexity of managing a WebSocket connection. When your component mounts, useSubscription establishes a connection to the relay service, subscribes to the specified channel, and returns a subscription object. This object can then be used to listen for incoming events. The hook also handles cleanup, disconnecting and unsubscribing when the component unmounts.
Usage#
To use the hook, simply pass the channel you wish to subscribe to. It's critical that the channel name does not contain special characters like /, ., or :, as this will prevent the client from receiving events.
Parameters#
Name | Type | Description |
|---|---|---|
|
| Required. A unique identifier for the subscription channel. The hook prefixes this with the application ID to create the final channel name (e.g., |
Return Value#
The hook returns a subscription object, which is an instance of the WebSocket client's subscription handler. You can attach event listeners to this object using its .on(eventName, callback) method.
Example#
Here is an example of a component that displays the status of an invoice. It uses useSubscription to listen for real-time updates and changes the status from "Pending" to "Paid" when an invoice.paid event is received.
import React, { useState, useEffect } from 'react';
import { useSubscription } from '@blocklet/payment-react';
interface InvoiceStatusProps {
invoiceId: string;
initialStatus: 'pending' | 'paid' | 'failed';
}
function InvoiceStatus({ invoiceId, initialStatus }: InvoiceStatusProps) {
const [status, setStatus] = useState(initialStatus);
// The channel should be a simple string. The hook handles the rest.
const subscription = useSubscription(invoiceId);
useEffect(() => {
// Ensure the subscription object is available before attaching listeners
if (subscription) {
const handleInvoiceUpdate = (event) => {
console.log('Received event:', event);
if (event.status === 'paid') {
setStatus('paid');
}
};
// Listen for a generic 'update' or a specific event name
// The actual event name depends on your backend implementation.
subscription.on('invoice.paid', handleInvoiceUpdate);
// Cleanup function to remove the listener when the component
// unmounts or the subscription object changes.
return () => {
subscription.off('invoice.paid', handleInvoiceUpdate);
};
}
}, [subscription]); // Re-run effect if the subscription object changes
return (
<div>
<h2>Invoice Status</h2>
<p>Invoice ID: {invoiceId}</p>
<p>Status: <strong>{status.toUpperCase()}</strong></p>
</div>
);
}
export default InvoiceStatus;In this example:
- The component subscribes to a channel named after the
invoiceId. - An effect is set up to listen for the
subscriptionobject. - Once the
subscriptionobject is available, an event handlerhandleInvoiceUpdateis attached to theinvoice.paidevent. - When a matching event is received from the server, the handler updates the component's state, and the UI re-renders to show the "PAID" status.
- The
useEffectcleanup function ensures the event listener is removed to prevent memory leaks.