Leptos-Use Guide

use_websocket

Creating and managing a Websocket connection.

Demo

Usage

use leptos::*;
use leptos_use::{use_websocket, UseWebsocketReturn};
use leptos_use::core::ConnectionReadyState;

#[component]
fn Demo() -> impl IntoView {
let UseWebsocketReturn {
    ready_state,
    message,
    message_bytes,
    send,
    send_bytes,
    open,
    close,
    ..
} = use_websocket("wss://echo.websocket.events/");

let send_message = move |_| {
    send("Hello, world!");
};

let send_byte_message = move |_| {
    send_bytes(b"Hello, world!\r\n".to_vec());
};

let status = move || ready_state.get().to_string();

let connected = move || ready_state.get() == ConnectionReadyState::Open;

let open_connection = move |_| {
    open();
};

let close_connection = move |_| {
    close();
};

view! {
    <div>
        <p>"status: " {status}</p>

        <button on:click=send_message disabled=move || !connected()>"Send"</button>
        <button on:click=send_byte_message disabled=move || !connected()>"Send bytes"</button>
        <button on:click=open_connection disabled=connected>"Open"</button>
        <button on:click=close_connection disabled=move || !connected()>"Close"</button>

        <p>"Receive message: " {move || format!("{:?}", message.get())}</p>
        <p>"Receive byte message: " {move || format!("{:?}", message_bytes.get())}</p>
    </div>
}
}

Relative Paths

If the provided url is relative, it will be resolved relative to the current page. Urls will be resolved like this the following. Please note that the protocol (http vs https) will be taken into account as well.

Current PageRelative UrlResolved Url
http://example.com/some/where/api/wsws://example.com/api/ws
https://example.com/some/where/api/wswss://example.com/api/ws
https://example.com/some/whereapi/wswss://example.com/some/where/api/ws
https://example.com/some/where//otherdomain.com/api/wswss://otherdomain.com/api/ws

Usage with provide_context

The return value of use_websocket utilizes several type parameters which can make it cumbersome to use with provide_context + expect_context. The following example shows how to avoid type parameters with dynamic dispatch. This sacrifices a little bit of performance for the sake of ergonomics. However, compared to network transmission speeds this loss of performance is negligible.

First we define the struct that is going to be passed around as context.

use leptos::*;
use std::rc::Rc;

#[derive(Clone)]
pub struct WebsocketContext {
    pub message: Signal<Option<String>>,
    send: Rc<dyn Fn(&str)>,  // use Rc to make it easily cloneable
}

impl WebsocketContext {
    pub fn new(message: Signal<Option<String>>, send: Rc<dyn Fn(&str)>) -> Self {
        Self {
            message,
            send,
        }
    }

    // create a method to avoid having to use parantheses around the field
    #[inline(always)]
    pub fn send(&self, message: &str) {
        (self.send)(message)
    }
}

Now you can provide the context like the following.

use leptos::*;
use leptos_use::{use_websocket, UseWebsocketReturn};
use std::rc::Rc;
#[derive(Clone)]
pub struct WebsocketContext {
    pub message: Signal<Option<String>>,
    send: Rc<dyn Fn(&str)>,
}

impl WebsocketContext {
    pub fn new(message: Signal<Option<String>>, send: Rc<dyn Fn(&str)>) -> Self {
        Self {
            message,
            send,
        }
    }
}

#[component]
fn Demo() -> impl IntoView {
let UseWebsocketReturn {
    message,
    send,
    ..
} = use_websocket("ws:://some.websocket.io");

provide_context(WebsocketContext::new(message, Rc::new(send.clone())));

view! {}
}

Finally let's use the context:

use leptos::*;
use leptos_use::{use_websocket, UseWebsocketReturn};
use std::rc::Rc;
#[derive(Clone)]
pub struct WebsocketContext {
    pub message: Signal<Option<String>>,
    send: Rc<dyn Fn(&str)>,
}

impl WebsocketContext {
    #[inline(always)]
    pub fn send(&self, message: &str) {
        (self.send)(message)
    }
}

#[component]
fn Demo() -> impl IntoView {
let websocket = expect_context::<WebsocketContext>();

websocket.send("Hello World!");

view! {}
}

Server-Side Rendering

On the server the returned functions amount to no-ops.

Types

Source

SourceDemoDocs