Modern, Real-Time Web App With SignalR

25.02.2020

Modern, Real-Time Web App With SignalR

SignalR is a Microsoft library for ASP .NET, which enables real-time communications between server and client. This functionality allows for instant messages pushing from server to client. Client, hence, displays updates without doing a complete page refresh. Use cases for real-time web apps would be social network app, dashboard, monitoring…

SignalR Hub

Hubs make it feasible for client-to-server and server-to-client communication. Hubs contain public methods that can be called from client side and vice versa, hubs can call functions that are defined on client code.

Example of a hub:

using Microsoft.AspNetCore.SignalR;

namespace API.SignalR
{
    public class MessengerHub : Hub
    {
//Send message to specified group
        public async Task SendMessageToGroup(message)
        {
            await Clients.Group(groupName).SendAsync("ReceiveMessage", message);
        }

 //Send message to all
        public async Task SendMessage(message)
        {
            await Clients.All.SendAsync("ReceiveMessage", message);
        }

 //Send message to Caller
        public async Task SendMessageToGroup(message)
        {
            await Clients.Caller.SendAsync("ReceiveMessage", message);
        }

//Methods to add to group and remove from group 
        public async Task AddToGroup(string groupName)
        {
            await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
            await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group");
        }
}

Client-Side React

Installation: npm install @microsoft/signalr

Setup connection to hub with React hook

import React, { useEffect, useState } from "react";
import {
  HubConnection,
  HubConnectionBuilder,
  LogLevel
} from "@microsoft/signalr";

  const TopicChat = () => {
  const [hubConnection, setHubConnection] = useState<HubConnection>();

  //addMessage function to invoke SendMessageToGroup from server
  const addMessage = async (values: any) => {
    try {
     await hubConnection!.Invoke("SendMessageToGroup", values)
    } catch (err) {
     console.log(err)
    }
  }

  useEffect(() => {
    const createHubConnection = async () => {
      const connect = new HubConnectionBuilder()
        .withUrl("http://localhost:5000/chat", {
          accessTokenFactory: () => this.rootStore.token!
        })
        .configureLogging(LogLevel.Information)
        .build();
      try {
        await connect.start()
        //Invoke method defined in server to add user to a specified group
      } catch (err) {
        console.log(err)
      }
      setHubConnection(connect)
    }
    createHubConnection()
    
    return (() => cleanUpFunction(//Stop the hub connection when Chat Component is closed))
  }, [])

  return (JSX to trigger addMessage)
}

export default TopicChat

Code Explanation:

In the example above, I’ve used useEffect to connect to our SignalR hub and set local state for successful hub connection. At the same time, I add current user to a chosen group. Notice in the return part of useEffect, I clean up my effect by stopping the hub connection after component unmounts.

In TopicChat Component, I have some JSX code that can trigger addMessage method I define above. In addMessage, I invoke SendMessageToGroup method from our hub. From there, hub will send updates to all connected clients that belong to that group. Boom! Other clients in the same group get instantly the update.

Share
Contact Person

Blog writer

Nhu Kangasniemi

Junior Developer