useWebSocket.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  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. onMessage: (payload: WSMessage<T>) => void;
  9. onError?: (error: Event) => void;
  10. onClose?: () => void;
  11. }
  12. export function useWebSocket<T>({
  13. conversationId,
  14. enabled = true,
  15. isVisitor = true, // 默认是访客
  16. onMessage,
  17. onError,
  18. onClose,
  19. }: UseWebSocketOptions<T>) {
  20. // 使用 useRef 存储最新的回调函数,避免因回调函数变化导致重新连接
  21. const onMessageRef = useRef(onMessage);
  22. const onErrorRef = useRef(onError);
  23. const onCloseRef = useRef(onClose);
  24. // 更新 ref 的值
  25. useEffect(() => {
  26. onMessageRef.current = onMessage;
  27. onErrorRef.current = onError;
  28. onCloseRef.current = onClose;
  29. }, [onMessage, onError, onClose]);
  30. useEffect(() => {
  31. if (!conversationId || !enabled) {
  32. return;
  33. }
  34. const client = new WSClient<T>({
  35. conversationId,
  36. isVisitor,
  37. // 使用 ref 的 current 值,这样即使回调函数变化也不会导致重新连接
  38. onMessage: (payload) => onMessageRef.current(payload),
  39. onError: onErrorRef.current
  40. ? (error) => onErrorRef.current?.(error)
  41. : undefined,
  42. onClose: onCloseRef.current ? () => onCloseRef.current?.() : undefined,
  43. });
  44. client.connect();
  45. return () => {
  46. client.disconnect();
  47. };
  48. // 只依赖 conversationId、enabled 和 isVisitor,不依赖回调函数
  49. // 回调函数通过 useRef 存储,不会导致重新连接
  50. }, [conversationId, enabled, isVisitor]);
  51. }