2024-12-20 13:34:26 +01:00
2024-08-09 10:32:59 +02:00
2024-12-20 13:34:26 +01:00
2020-10-23 11:00:54 -05:00
2024-01-11 14:33:53 +01:00
2022-01-12 18:13:50 +00:00
2024-12-20 12:39:31 +00:00
2024-01-11 14:33:53 +01:00
2020-07-23 14:23:21 -05:00
2020-09-04 00:00:15 -05:00
2020-06-21 13:21:54 -05:00
2020-06-21 13:21:54 -05:00
2024-09-03 16:55:50 +02:00
2020-06-21 13:21:54 -05:00
2024-12-20 13:34:26 +01:00
2020-06-21 13:21:54 -05:00
2020-06-21 13:21:54 -05:00
2020-06-21 13:21:54 -05:00
2020-06-29 13:45:31 -05:00
2020-10-23 11:00:54 -05:00
2024-12-20 12:39:31 +00:00
2020-06-29 13:24:10 -05:00
2025-03-05 07:33:44 +01:00
2020-09-20 19:14:26 -05:00

Fable.SignalR Nuget

Fable bindings for the SignalR client, a wrapper for the .NET client, and ASP.NET Core/Giraffe/Saturn wrappers for SignalR server hubs.

The full documentation can be found here.

On the client

let textDisplay = React.functionComponent(fun (input: {| count: int; text: string |}) ->
    React.fragment [
        Html.div input.count
        Html.div input.text
    ])

let buttons = React.functionComponent(fun (input: {| count: int; hub: Hub<Action,Response> |}) ->
    React.fragment [
        Html.button [
            prop.text "Increment"
            prop.onClick <| fun _ -> input.hub.current.sendNow (Action.IncrementCount input.count)
        ]
        Html.button [
            prop.text "Decrement"
            prop.onClick <| fun _ -> input.hub.current.sendNow (Action.DecrementCount input.count)
        ]
        Html.button [
            prop.text "Get Random Character"
            prop.onClick <| fun _ -> input.hub.current.sendNow Action.RandomCharacter
        ]
    ])

let render = React.functionComponent(fun () ->
    let count,setCount = React.useState 0
    let text,setText = React.useState ""

    let hub =
        React.useSignalR<Action,Response>(fun hub -> 
            hub.withUrl(Endpoints.Root)
                .withAutomaticReconnect()
                .configureLogging(LogLevel.Debug)
                .onMessage <|
                    function
                    | Response.NewCount i -> setCount i
                    | Response.RandomCharacter str -> setText str
        )
            
    Html.div [
        prop.children [
            textDisplay {| count = count; text = text |}
            buttons {| count = count; hub = hub |}
        ]
    ])

On the server

module SignalRHub =
    open FSharp.Control.Tasks.V2

    let update (msg: Action) =
        match msg with
        | Action.IncrementCount i -> Response.NewCount(i + 1)
        | Action.DecrementCount i -> Response.NewCount(i - 1)
        | Action.RandomCharacter ->
            let characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
            
            System.Random().Next(0,characters.Length-1)
            |> fun i -> characters.ToCharArray().[i]
            |> string
            |> Response.RandomCharacter

    let invoke (msg: Action) _ =
        task { return update msg }

    let send (msg: Action) (hubContext: FableHub<Action,Response>) =
        update msg
        |> hubContext.Clients.Caller.Send

application {
    use_signalr (
        configure_signalr {
            endpoint Endpoints.Root
            send SignalRHub.send
            invoke SignalRHub.invoke
        }
    )
    ...
}

The shared file

[<RequireQualifiedAccess>]
type Action =
    | IncrementCount of int
    | DecrementCount of int
    | RandomCharacter

[<RequireQualifiedAccess>]
type Response =
    | NewCount of int
    | RandomCharacter of string

module Endpoints =
    let [<Literal>] Root = "/SignalR"
Description
No description provided
Readme MIT 2 MiB
v2.1.0 Latest
2024-12-20 12:39:34 +00:00
Languages
F# 97.6%
JavaScript 2.1%
Dockerfile 0.3%