useWebSocket.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. "use client";
  2. import { useEffect, useRef } from "react";
  3. import { WSClient, WSMessage } from "@/lib/websocket";
  4. interface UseWebSocketOptions<T> {
  5. conversationId: number | null;
  6. enabled?: boolean;
  7. isVisitor?: boolean; // 是否是访客(默认为 true)
  8. agentId?: number; // 客服ID(如果是客服连接,需要传递)
  9. onMessage: (payload: WSMessage<T>) => void;
  10. onError?: (error: Event) => void;
  11. onClose?: () => void;
  12. }
  13. export function useWebSocket<T>({
  14. conversationId,
  15. enabled = true,
  16. isVisitor = true, // 默认是访客
  17. agentId,
  18. onMessage,
  19. onError,
  20. onClose,
  21. }: UseWebSocketOptions<T>) {
  22. // 使用 useRef 存储最新的回调函数,避免因回调函数变化导致重新连接
  23. const onMessageRef = useRef(onMessage);
  24. const onErrorRef = useRef(onError);
  25. const onCloseRef = useRef(onClose);
  26. // 更新 ref 的值
  27. useEffect(() => {
  28. onMessageRef.current = onMessage;
  29. onErrorRef.current = onError;
  30. onCloseRef.current = onClose;
  31. }, [onMessage, onError, onClose]);
  32. useEffect(() => {
  33. if (!conversationId || !enabled) {
  34. return;
  35. }
  36. const client = new WSClient<T>({
  37. conversationId,
  38. isVisitor,
  39. agentId,
  40. // 使用 ref 的 current 值,这样即使回调函数变化也不会导致重新连接
  41. onMessage: (payload) => onMessageRef.current(payload),
  42. onError: onErrorRef.current
  43. ? (error) => onErrorRef.current?.(error)
  44. : undefined,
  45. onClose: onCloseRef.current ? () => onCloseRef.current?.() : undefined,
  46. });
  47. client.connect();
  48. return () => {
  49. client.disconnect();
  50. };
  51. // 只依赖 conversationId、enabled、isVisitor 和 agentId,不依赖回调函数
  52. // 回调函数通过 useRef 存储,不会导致重新连接
  53. }, [conversationId, enabled, isVisitor, agentId]);
  54. }