Connecting to SignalR from React Native Expo app

Viewed 848

I'm trying to connect to my SignalR hub from a new React Native Expo app and I keep getting an error, though the nature of the error is unclear because there's no data provided with the error.

As I said, this is a brand new Expo app so the code is very simple:

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';

const connection = new HubConnectionBuilder()
  .withUrl('https://my-app.com/test-chat')
  .configureLogging(LogLevel.Information)
  .build();

async function start() {
  debugger;
  try {
    await connection.start();
    debugger;
    console.log('SignalR Connected.');
  } catch (err) {
    debugger;
    console.log(err);
    setTimeout(start, 5000);
  }
}

connection.onclose(async () => {
  await start();
});

// Start the connection.
start();

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Hello World!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Here's what I see in my console: enter image description here

The npm package I use for SignalR in the app is "@microsoft/signalr": "^5.0.9".

And here's the code in my test-chat hub:

public class TestChat : Hub
{
    public override async Task OnConnectedAsync()
    {
        var connectionId = Context.ConnectionId;

        await Groups.AddToGroupAsync(connectionId, "test-chat");
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var connectionId = Context.ConnectionId;

        await Groups.RemoveFromGroupAsync(connectionId, "test-chat");
        await base.OnDisconnectedAsync(exception);
    }

    public async Task Send(string message)
    {
        await Clients.Groups("test-chat").SendAsync("new_message", message);
    }
}

I tried connecting in debug mode locally. I also tried connecting to it on an actual app on the web. Either way, the connection is failing. I thought it could be a CORS issue but I don't think we specify anything in the CORS settings for mobile apps.

Any idea what could be the issue here? Has anyone been able to connect to a SignalR hub using React Native (Expo or not)?

UPDATE: One important point I forgot to mention originally is that I'm using Azure SignalR. My Expo client app is still configured to hit the hub that's on my ASP.NET Core backend.

UPDATE 2: First, there was a CORS issue because I was testing this using the Android simulator on my Windows 10 machine and I needed to add http://localhost:19000 to allowed origins. But the second issue is more concerning to me: I do use the Azure SignalR service to make things more reliable and scalable but that's creating an issue. When I switched to just handling all client connections in my ASP.NET Core 5 backend, it started to work.

1 Answers

Given the nature of the question and the lack of knowledge about the libraries involved I cannot give you an answer as nice I'd like to give but I can try to point you in the right direction.

I've tracked down where your error is emitted in the library code. That would be the HttpConnection class. That itself is constructed in the more familiar HubConnectionBuilder.

I would suggest placing a breakpoint inside the library code to further debug you issue. Right about here would be a nice spot. Doing so should allow you to easily inspect the parameters that were used to create the request, and spot potential errors.

Now, where is the library code in your local disk? Well there could be two locations. While I'm sure somebody out there knows how to determine this, I do not. The "issue" is that the library exposes two types of modules. The cjs folder, and the esm one (technically there is also browser and webworker, but I think it is unlikely to be one of those). Now you might wonder what those folders stand for, which the package.json of that module answer at least to a certain extent. cjs stands for "common js" and esm stands for "ES modules". Anyway... to the point... like I said I don't know what type of module the bundler of react-native is using (and it is very likely you can configure it via some sort of config), so I would honestly just start by first placing the breakpoint in node_modules/@microsoft/signalr/dist/esm/HttpConnection.js, and if that breakpoint doesn't hit, try node_modules/@microsoft/signalr/dist/cjs/HttpConnection.js.

There you go. If I may be of any further assistance, please write a comment!

Related