Typed SignalR hooks for every framework

One core, seven adapters. Declare your hubs once and get typed events, typed calls, and a connection that recovers by itself.

import { useState } from "react";
import { createSignalRClient, method } from "@dammers/use-signalr-react";

const { SignalRProvider, useSignalRInvoke } = createSignalRClient({
  hubs: {
    "/hubs/rooms": {
      methods: { GetHistory: method<[roomId: string], { text: string }[]>() },
    },
  },
});

function HistoryCount({ roomId }: { roomId: string }) {
  const getHistory = useSignalRInvoke("/hubs/rooms", "GetHistory");
  const [count, setCount] = useState(0);
  const load = () => getHistory(roomId).then((m) => setCount(m.length)).catch(console.error);
  return <button onClick={load}>{count} messages</button>;
}

export function App() {
  return (
    <SignalRProvider baseUrl="https://api.example.com" accessTokenFactory={() => "token"}>
      <HistoryCount roomId="general" />
    </SignalRProvider>
  );
}

Pick your framework

Typed from one contract

Declare hubs, events and methods once. Every event handler and invoke is typed from that contract.

Many hubs, one provider

One client serves all hubs. Each hub connects once, however many components use it.

Lazy hubs

A lazy hub connects when the first consumer mounts and stops after the last one leaves.

Recovers by itself

A lost connection comes back without app code. Reconnect callbacks let you refetch.

Teardown that lands

A leave call in a cleanup waits for the connection and is sent once.

SSR-safe, no runtime deps

Nothing connects on the server. Framework and SignalR packages are peers.

MIT License · GitHub · Framework logos from Simple Icons; the Angular logo is CC BY 4.0, the Vue logo is CC BY-NC-SA 4.0.