Source: data/SignalROqt.js

  1. import React, { useCallback, useEffect, useRef, useState } from "react";
  2. import { useSelector } from "react-redux";
  3. import * as immutable from 'object-path-immutable';
  4. import { SignalRContext } from "../../_core/contexts";
  5. import { booleanString, useHooks } from "../..";
  6. const signalR = require("@microsoft/signalr");
  7. /**
  8. * Componente que crea un contexto de signalr para todos los watcher que contenga
  9. * @name Reactor.Components.Data.SignalROqt
  10. * @param {string} hub Url del endpoint de SignalR
  11. * @param {BooleanString} [debug = "true"]
  12. * @class
  13. * @example
  14. <signalr hub="http://www.orquesta.com.ar/signalr">
  15. <watcher monitor="mensajes" hooks="ActualizarMensajes"></watcher>
  16. <watcher monitor="saldo" hooks="ActualizarSaldo"></watcher>
  17. <div>
  18. ...lista de mensajes
  19. </div>
  20. </signalr>
  21. */
  22. const SignalROqt = ({hub, children, onreconnect, debug = "false"}) => {
  23. //const isAuth = useSelector(state => state.app.isAuth);
  24. //const online = useSelector(state => state.app.variables.app.online);
  25. //const variables = useVariables();
  26. const jwt = useSelector(state => state.app.jwt?.token);
  27. const connection = useRef();
  28. const subscriptions = useRef({});
  29. const [state, setState] = useState("stop");
  30. const { procesarHooks } = useHooks({silent: "true", onreconnect, debug});
  31. useEffect(()=>{
  32. booleanString(debug) && console.log("SignalR", {event: "load", jwt, hub});
  33. if(!hub) return;
  34. if(!jwt && connection.current){
  35. connection.current?.stop();
  36. connection.current = undefined;
  37. return;
  38. }
  39. if(!jwt)return;
  40. connection.current = new signalR.HubConnectionBuilder()
  41. .withUrl(hub, {
  42. accessTokenFactory: () => jwt,
  43. withCredentials: false
  44. })
  45. .configureLogging(debug === "true" ? signalR.LogLevel.Debug : signalR.LogLevel.None)
  46. .withAutomaticReconnect()
  47. .build();
  48. connection.current.onreconnected(onReconnected);
  49. start()
  50. .then(()=>{
  51. setState("start");
  52. })
  53. .catch(e => {
  54. booleanString(debug) && console.log("SignalR", e);
  55. });
  56. }, [jwt, hub]);
  57. const onResponse = useCallback((message)=>{
  58. booleanString(debug) && console.log("SignalR", {event: "response", message, subscriptions: subscriptions.current});
  59. if(message.monitor && subscriptions.current[message.monitor]){
  60. try{
  61. subscriptions.current[message.monitor]?.callback();
  62. }catch(e){}
  63. }
  64. /*
  65. if(data.mensaje === "stop"){
  66. connection.current.stop().then(()=>{
  67. console.log("se desconecto")
  68. });
  69. }
  70. connection.current.on("close", function (data) { });
  71. */
  72. }, []);
  73. const onReconnected = useCallback(()=>{
  74. booleanString(debug) && console.log("SignalR", {subscriptions: subscriptions.current})
  75. procesarHooks();
  76. Object.values(subscriptions.current).forEach(subscription => {
  77. subscription.reconnectCallback()
  78. });
  79. }, []);
  80. useEffect(()=>{
  81. if(state === "start"){
  82. connection.current?.on("response", onResponse);
  83. }
  84. return ()=>{
  85. connection.current?.off("response");
  86. }
  87. }, [state, onResponse])
  88. const start = async () => {
  89. await connection.current.start();
  90. }
  91. const subscribe = useCallback(({monitor, callback, reconnectCallback}) => {
  92. connection.current.invoke("Subscribe", monitor)
  93. .then(()=>{
  94. subscriptions.current[monitor] = {callback, reconnectCallback};
  95. booleanString(debug) && console.log("SignalR", {event: "subscribe", subscriptions: subscriptions.current});
  96. })
  97. .catch(e => booleanString(debug) && console.log(e));
  98. }, [debug]);
  99. const unsubscribe = useCallback(({monitor}) => {
  100. connection.current.invoke("Unsubscribe", monitor).catch(e => booleanString(debug) && console.log(e));
  101. delete subscriptions.current[monitor];
  102. booleanString(debug) && console.log("SignalR", {event: "unsubscribe", monitor,subscriptions: subscriptions.current})
  103. }, [])
  104. return (
  105. <SignalRContext.Provider value={{subscribe, unsubscribe}}>
  106. {children}
  107. </SignalRContext.Provider>
  108. );
  109. }
  110. export default SignalROqt;