How to import SignalR in React Component?

后端 未结 4 665
谎友^
谎友^ 2020-12-30 10:02

I have used create-react-app to scaffold the initial react application.

My DashBoard component:

import React, { Co         


        
相关标签:
4条回答
  • 2020-12-30 10:06

    Check out SignalR no jQuery

    npm i -D signalr-no-jquery
    import { hubConnection } from 'signalr-no-jquery';
    
    const connection = hubConnection('http://[address]:[port]', options);
    const hubProxy = connection.createHubProxy('hubNameString');
    
    // set up event listeners i.e. for incoming "message" event
    hubProxy.on('message', function(message) {
        console.log(message);
    });
    
    // connect
    connection.start({ jsonp: true })
      .done(function(){ console.log('Now connected, connection ID=' + connection.id); })
      .fail(function(){ console.log('Could not connect'); });
    

    https://www.npmjs.com/package/signalr-no-jquery

    0 讨论(0)
  • 2020-12-30 10:28

    UPDATE: Please note that if you are using Redux in your ReactJS app, the solution below is not necessarily the best solution. It is better to implement signalR as a middleware. You can find the best answer here.

    If you are not using Redux, or you still want to implement it in a React component, then read on: For people that are using the latest version of signalR (core v2.1), since jQuery is not a dependency of signalR any more, you can import it like:

    import * as signalR from '@aspnet/signalr';
    

    NOTE: there is now a newer version of signalr available (@microsoft/signalr) that requires a different setup. This solution only works with @aspnet/signalr. (UPDATE June 2020)

    And then use it like:

    signalR.HubConnectionBuilder()
    

    Here is an example:

    import React, { PureComponent } from 'react';
    import { string } from 'prop-types';
    import * as signalR from '@aspnet/signalr';
    
    class SignalR extends PureComponent {
      constructor (props) {
        super(props);
    
        this.connection = null;
        this.onNotifReceived = this.onNotifReceived.bind(this);
      }
    
      componentDidMount () {
        const protocol = new signalR.JsonHubProtocol();
    
        const transport = signalR.HttpTransportType.WebSockets;
    
        const options = {
          transport,
          logMessageContent: true,
          logger: signalR.LogLevel.Trace,
          accessTokenFactory: () => this.props.accessToken,
        };
    
        // create the connection instance
        this.connection = new signalR.HubConnectionBuilder()
          .withUrl(this.props.connectionHub, options)
          .withHubProtocol(protocol)
          .build();
    
        this.connection.on('DatabaseOperation', this.onNotifReceived);
        this.connection.on('DownloadSession', this.onNotifReceived);
        this.connection.on('UploadSession', this.onNotifReceived);
    
        this.connection.start()
          .then(() => console.info('SignalR Connected'))
          .catch(err => console.error('SignalR Connection Error: ', err));
      }
    
      componentWillUnmount () {
        this.connection.stop();
      }
    
      onNotifReceived (res) {
        console.info('Yayyyyy, I just received a notification!!!', res);
      }
    
      render () {
        return <span />;
      };
    };
    
    SignalR.propTypes = {
      connectionHub: string.isRequired,
      accessToken: string.isRequired
    };
    
    export default SignalR;
    

    UPDATE: in 2020, you can use "withAutomaticReconnect()":

      const connection = new HubConnectionBuilder()
        .withUrl(connectionHub, options)
        .withAutomaticReconnect()
        .withHubProtocol(new JsonHubProtocol())
        .configureLogging(LogLevel.Information)
        .build();
    
    0 讨论(0)
  • 2020-12-30 10:29

    What I figured out Signalr has dependency on jQuery. For some reason import $ from 'jquery' doesn't set window.jQuery. That's why need to do it explicitly.

    I solved the issue this way:

    import React, { Component } from 'react';
    import { Link } from 'react-router-dom';
    import $ from 'jquery';
    window.jQuery = $;
    require('signalr');
    
    class Dashboard extends Component {
       // .....   
    }
    
    export default Dashboard;
    
    0 讨论(0)
  • 2020-12-30 10:31

    This is how we do it now (year 2020) with the new package @microsoft/signalr. We use Redux, but you don't have to use Redux to be able to utilize this method.

    If you are using @microsoft/signalr package instead of @aspnet/signalr, then this is how you can set it up. This is our working code in prod:

    import {
      JsonHubProtocol,
      HubConnectionState,
      HubConnectionBuilder,
      LogLevel
    } from '@microsoft/signalr';
    
    const isDev = process.env.NODE_ENV === 'development';
    
    const startSignalRConnection = async connection => {
      try {
        await connection.start();
        console.assert(connection.state === HubConnectionState.Connected);
        console.log('SignalR connection established');
      } catch (err) {
        console.assert(connection.state === HubConnectionState.Disconnected);
        console.error('SignalR Connection Error: ', err);
        setTimeout(() => startSignalRConnection(connection), 5000);
      }
    };
    
    // Set up a SignalR connection to the specified hub URL, and actionEventMap.
    // actionEventMap should be an object mapping event names, to eventHandlers that will
    // be dispatched with the message body.
    export const setupSignalRConnection = (connectionHub, actionEventMap = {}, getAccessToken) => (dispatch, getState) => {
      const options = {
        logMessageContent: isDev,
        logger: isDev ? LogLevel.Warning : LogLevel.Error,
        accessTokenFactory: () => getAccessToken(getState())
      };
      // create the connection instance
      // withAutomaticReconnect will automatically try to reconnect
      // and generate a new socket connection if needed
      const connection = new HubConnectionBuilder()
        .withUrl(connectionHub, options)
        .withAutomaticReconnect()
        .withHubProtocol(new JsonHubProtocol())
        .configureLogging(LogLevel.Information)
        .build();
    
      // Note: to keep the connection open the serverTimeout should be
      // larger than the KeepAlive value that is set on the server
      // keepAliveIntervalInMilliseconds default is 15000 and we are using default
      // serverTimeoutInMilliseconds default is 30000 and we are using 60000 set below
      connection.serverTimeoutInMilliseconds = 60000;
    
      // re-establish the connection if connection dropped
      connection.onclose(error => {
        console.assert(connection.state === HubConnectionState.Disconnected);
        console.log('Connection closed due to error. Try refreshing this page to restart the connection', error);
      });
    
      connection.onreconnecting(error => {
        console.assert(connection.state === HubConnectionState.Reconnecting);
        console.log('Connection lost due to error. Reconnecting.', error);
      });
    
      connection.onreconnected(connectionId => {
        console.assert(connection.state === HubConnectionState.Connected);
        console.log('Connection reestablished. Connected with connectionId', connectionId);
      });
    
      startSignalRConnection(connection);
    
      connection.on('OnEvent', res => {
        const eventHandler = actionEventMap[res.eventType];
        eventHandler && dispatch(eventHandler(res));
      });
    
      return connection;
    };
    

    Then you would call like the following. Please note that this a pseudo code. You may have to call it differently depending on your project setup.

    import { setupSignalRConnection } from 'fileAbove.js';
    
    const connectionHub = '/hub/service/url/events';
    
    export const setupEventsHub = setupSignalRConnection(connectionHub, {
      onMessageEvent: someMethod
    }, getAccessToken);
    
    export default () => dispatch => {
      dispatch(setupEventsHub); // dispatch is coming from Redux
    };
    

    Let me know if it helped by up-voting. Thank you

    0 讨论(0)
提交回复
热议问题