Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
let inline websocket<'Data> =
FunctionComponent.Of(fun (props: {| url : string; retryTimeSpan : TimeSpan; onConnected: bool -> unit; onMessage: 'Data -> unit |}) ->
let mutable currentlyConnected = false
let mutable wasAlreadyConnected = false
let connected = Hooks.useState false
let mutable webservice = null
let connect() =
if currentlyConnected then () else
let ws = WebSocket.Create(props.url)
ws.onclose <- unbox (fun _ ->
match ws.readyState with
| WebSocketState.CLOSED ->
currentlyConnected <- false
connected.update (fun _ -> currentlyConnected)
| _ -> ()
)
ws.onmessage <- unbox (fun (msg: MessageEvent) ->
let msg' = msg.data |> string
if not (System.String.IsNullOrWhiteSpace msg') then
let decoded = ServerCode.JSON.ofJson<'Data> msg'
props.onMessage decoded
unbox None
)
ws.onopen <- unbox (fun _ ->
match ws.readyState with
| WebSocketState.OPEN ->
props.onConnected wasAlreadyConnected
currentlyConnected <- true
wasAlreadyConnected <- true
connected.update (fun _ -> currentlyConnected)
| _ -> ()
)
webservice <- ws
let register() =
let retry = setInterval (fun _ -> connect()) (int props.retryTimeSpan.TotalMilliseconds)
connect()
{ new IDisposable with
member __.Dispose() =
clearInterval(retry)
if not (isNull webservice) then
webservice.close()
}
Hooks.useEffectDisposable(register,[||])
if connected.current then str "Connected" else str "Disconnected"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment