4

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.

Kartikey
  • 4,516
  • 4
  • 15
  • 40
Sam
  • 26,817
  • 58
  • 206
  • 383
  • Well while I don't know what "signalr" is, I've worked with react-native quite a bit now, and I don't think the issue is related to that. "CORS" e.g. cross origin resource sharing, is a standard implemented by the browser, so if you make an HTTP request (for example wit the `node-fetch` module) from node, it is not subject to CORS at all. I would suggest running your requests in the browser first, and figure out the issue there. I'm almost certain you are looking at the wrong place, searching the issue in `react-native` or `expo`. – Elias Sep 17 '21 at 19:26
  • "though the nature of the error is unclear because there's no data provided with the error.", funny, according to the library they include error information. The error seems to be `Error` (e.g. the part of the error message after the `:`). lol. – Elias Sep 17 '21 at 19:48
  • In which mode are you using Azure SignalR Service? Serverless, Default or Classic? Saying that switching back to your client connections hitting the asp.net core 5 backend implies Default? Are you wanting to use Serverless? – 97ldave Sep 20 '21 at 16:34
  • I'm using the default mode where I do have a hub on my ASP.NET Core backend app. I'm trying to use the Azure SignalR service to help manage all client connections. It's my understanding that Azure SignalR service is a better choice for reliability and scalability which is why I chose to use it. – Sam Sep 20 '21 at 17:37
  • Your client still has to connect to the service via your hub to send/receive messages which is what your front end code looks like its doing. Have you set up hub endpoint in your startup? does your backed .net core app not give you a more detailed error? (if its hitting it) – 97ldave Sep 20 '21 at 20:13

1 Answers1

0

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!

Elias
  • 3,592
  • 2
  • 19
  • 42
  • Thanks for trying to help with this issue. All I can see so far is that it's failing to start a connection. It keeps hitting line 110 in `cjs\HttpConnection.js`. Beyond that I'm not yet sure what's going on. I think my hub is rejecting the connection. I put break points in the `OnConnectedAsync()` method but I'm not hitting it. – Sam Sep 17 '21 at 21:46
  • @Sam Did you look at the parameters that are used to open the connection? I strongly suspect that they are incorrect (or alternatively that the server is misconfigured). – Elias Sep 17 '21 at 22:02
  • Like the headers, credentials, url, etc? – Elias Sep 17 '21 at 22:03
  • Ah, and go up the call stack with the debugger until you reach the actual origin of the error "Error". That most certainly give you more context, again, I would love to try this out but I just don't have the setup. I assume it's not that easy to create some sort of reproducible repo? Also, have you tried the same in like normal node.js code? That will eliminate once and for all some issue with `react-native`. – Elias Sep 17 '21 at 22:08
  • Here's an update: 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. – Sam Sep 19 '21 at 19:42
  • Like I said, I'm quite sure the node HttpRequest does **not** have CORS. But I'm glad if it's working for you now. – Elias Sep 21 '21 at 04:28