跳到主要内容

useSubscription

useSubscription Hook 提供了一种使用 WebSocket 从支付服务订阅实时事件的简单方法。它处理连接、订阅和清理逻辑,让您可以专注于应用程序如何响应像 invoice.paid 这样的事件。

这对于创建动态用户体验至关重要,在这种体验中,UI 需要根据后端事件立即更新,而无需用户刷新页面。

工作原理

该 Hook 抽象了管理 WebSocket 连接的复杂性。当组件使用 useSubscription 时,它会与中继服务建立持久连接。然后,它会订阅您提供的特定 channel。该 Hook 会自动为您对通道进行命名空间化,构造一个格式为 relay:<app-id>:<your-channel> 的最终通道名称。

当后端服务向该通道发布事件时,Hook 的订阅对象会发出该事件,您的组件可以监听该事件。

useSubscription

参数

该 Hook 接受一个字符串参数。

参数类型描述是否必需
channelstring您想要监听的事件流的唯一标识符。重要提示:此字符串不得包含 /.: 等分隔符。

返回值

该 Hook 从底层的 @arcblock/ws 客户端库返回一个 subscription 对象。在建立连接期间,此对象最初可能为 null

一旦连接成功,返回的对象将提供管理事件监听器的方法:

  • subscription.on(eventName, handler): 附加一个事件监听器。
  • subscription.off(eventName, handler): 移除一个事件监听器。

使用示例

以下是一个实时跟踪发票状态的组件示例。当后端在发票的通道上广播 invoice.paid 事件时,组件的 UI 会自动更新。

Real-time Invoice Status Tracker

tsx
import { useSubscription } from '@blocklet/payment-react';
import React, { useState, useEffect } from 'react';

/**
 * 一个显示发票状态并在收到 'invoice.paid' 事件时实时更新的组件。
 */
function InvoiceStatusTracker({ invoiceId }) {
  const [status, setStatus] = useState('pending');
  // 订阅专用于此发票的通道
  const subscription = useSubscription(invoiceId);

  useEffect(() => {
    // WebSocket 连接建立后,subscription 对象才可用。
    if (subscription) {
      const handlePaymentSuccess = (eventData) => {
        console.log(`收到通道 ${invoiceId} 的 'invoice.paid' 事件:`, eventData);
        // 根据事件更新组件的状态
        setStatus('paid');
      };

      // 附加 'invoice.paid' 事件的监听器
      subscription.on('invoice.paid', handlePaymentSuccess);

      // 在组件卸载或 subscription 对象更改时清理事件监听器至关重要,以防止内存泄漏。
      return () => {
        subscription.off('invoice.paid', handlePaymentSuccess);
      };
    }
    // 如果 subscription 对象本身发生变化,此 effect 应重新运行。
  }, [subscription, invoiceId]);

  return (
    <div>
      <h2>Invoice Status</h2>
      <p>ID: {invoiceId}</p>
      <p>Status: <strong>{status.toUpperCase()}</strong></p>
      {status === 'pending' && <p>Waiting for payment confirmation...</p>}
      {status === 'paid' && <p>Payment confirmed! Your invoice is settled.</p>}
    </div>
  );
}

export default InvoiceStatusTracker;