I'm attempting to use RTK Query with a signalR websocket service to keep my react app up to date with server data.
My RTK API looks like this:
export const hubConnection = new signalR.HubConnectionBuilder()
.withUrl("https://localhost:7152/messagehub", {
withCredentials: false,
skipNegotiation: true,
logMessageContent: true,
logger: signalR.LogLevel.Information,
transport: signalR.HttpTransportType.WebSockets
})
.withAutomaticReconnect([0, 1000, 5000, 10000, 30000])
.build();
export const apiSlice = createApi({
reducerPath: 'apiSlice',
baseQuery: fetchBaseQuery({ baseUrl: 'https://localhost:7152' }),
endpoints: (builder) => ({
// these are the websocket / signalR endpoints
getNotifications: builder.query<NotificationType[], void>({
query: () => 'messagehub',
async onCacheEntryAdded(
arg,
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved },
) {
console.log(hubConnection.state); // PRINTS Disconnected
try {
// this loads the existing cache data
// await cacheDataLoaded; IF I UNCOMMENT THIS LINE, NOTHING FURTHER HAPPENS
if (hubConnection.state === signalR.HubConnectionState.Disconnected) {
console.log('SignalR connection is disconnected. Starting connection...'); // THIS MESSAGE PRINTS TO CONSOLE
await hubConnection.start().then(() => console.log("SignalR connection established")); // THIS MESSAGE PRINTS TO CONSOLE
}
hubConnection.on("ReceiveMessage", (notification: NotificationType) => {
console.log('StatusMessage', notification); // WITH THE cacheDataLoaded CALL COMMENTED OUT, THIS PRINTS WHEN A MESSAGE IS RECEIVED
updateCachedData((draft) => {
console.log('cache updating', draft); // THIS MESSAGE NEVER PRINTS
draft.push(notification) // THE STORE STAYS EMPTY
})
});
} catch (error) {
console.error('Failed to connect to SignalR hub:', JSON.parse(JSON.stringify(error)));
}
// this is a promise that resolves when the socket is no longer being used
await cacheEntryRemoved;
// close signalR connection
await hubConnection.stop();
}
}),
}),
})
First, the await cacheDataLoaded
method, if I leave it uncommented, blocks anything else from running. When I comment that out, I see an error on reload that says "Connection ID required", and while I know this is coming from SignalR, I don't know where / why.
In Redux devtools, the status of apiSlice.queries.getNotifications
shows status: rejected
. Again, I don't understand this message or where it's coming from-- there's nothing in logs / console showing any error in the code.
When I fire a test message from the signalR side, I see the message logged on the RTK Query side in the ReceiveMessage
handler, but the updateCachedData
method never fires. I wouldn't expect the ReceiveMessage
handler to get fired at all if the getNotifications
API was in a rejected
status?
Anyone got signalR websockets running with RTK Query? I've seen plenty of examples using signalR as middleware, and I've been able to get signalR running in a single component-- but I'm hoping to leverage the RTK Query side of things and so far I stumped.
cachedDataLoaded
is a method ononCacheEntryAdded
, It's commented out in the code above.