Skip to content

Instantly share code, notes, and snippets.

@anttisalonen
Created October 7, 2018 20:52
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anttisalonen/cb3cd19623ebad923740b90ea6ddf208 to your computer and use it in GitHub Desktop.
Save anttisalonen/cb3cd19623ebad923740b90ea6ddf208 to your computer and use it in GitHub Desktop.
yew + websocket echo client
#[macro_use]
extern crate yew;
extern crate failure;
use failure::Error;
use yew::prelude::*;
use yew::format::Json;
use yew::services::ConsoleService;
use yew::services::websocket::{WebSocketService, WebSocketStatus, WebSocketTask};
struct Model {
console: ConsoleService,
ws: Option<WebSocketTask>,
wss: WebSocketService,
link: ComponentLink<Model>,
text: String, // text in our input box
server_data: String, // data received from the server
}
enum Msg {
Connect, // connect to websocket server
Disconnected, // disconnected from server
Ignore, // ignore this message
TextInput(String), // text was input in the input box
SendText, // send our text to server
Received(Result<String, Error>), // data received from server
}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
Model {
console: ConsoleService::new(),
ws: None,
wss: WebSocketService::new(),
link: link,
text: String::new(),
server_data: String::new(),
}
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::Connect => {
self.console.log("Connecting");
let cbout = self.link.send_back(|Json(data)| Msg::Received(data));
let cbnot = self.link.send_back(|input| {
ConsoleService::new().log(&format!("Notification: {:?}", input));
match input {
WebSocketStatus::Closed | WebSocketStatus::Error => {
Msg::Disconnected
}
_ => Msg::Ignore,
}
});
if self.ws.is_none() {
let task = self.wss.connect("ws://127.0.0.1:8080/ws/", cbout, cbnot.into());
self.ws = Some(task);
}
true
}
Msg::Disconnected => {
self.ws = None;
true
}
Msg::Ignore => {
false
}
Msg::TextInput(e) => {
self.text = e; // note input box value
true
}
Msg::SendText => {
match self.ws {
Some(ref mut task) => {
task.send(Json(&self.text));
self.text = "".to_string();
true // clear input box
}
None => {
false
}
}
}
Msg::Received(Ok(s)) => {
self.server_data.push_str(&format!("{}\n", &s));
true
}
Msg::Received(Err(s)) => {
self.server_data.push_str(&format!("Error when reading data from server: {}\n", &s.to_string()));
true
}
}
}
}
impl Renderable<Model> for Model {
fn view(&self) -> Html<Self> {
html! {
// connect button
<p><button onclick=|_| Msg::Connect,>{ "Connect" }</button></p><br/>
// text showing whether we're connected or not
<p>{ "Connected: " } { !self.ws.is_none() } </p><br/>
// input box for sending text
<p><input type="text", value=&self.text, oninput=|e| Msg::TextInput(e.value),></input></p><br/>
// button for sending text
<p><button onclick=|_| Msg::SendText,>{ "Send" }</button></p><br/>
// text area for showing data from the server
<p><textarea value=&self.server_data,></textarea></p><br/>
}
}
}
fn main() {
yew::initialize();
App::<Model>::new().mount_to_body();
yew::run_loop();
}
@ssnover
Copy link

ssnover commented Jul 4, 2021

Thanks for posting this, this was the only example of yew websockets I could find! I had to make some updates in order to get it compiling with the current version of yew (0.18 right now). They're here for curious googlers: https://github.com/ssnover/yew-websockets-experiment/blob/56f8a01f728bf084315f79d77939a19759b608e3/src/main.rs

@hanusek
Copy link

hanusek commented Jan 8, 2022

@ssnover Could you update to yew 0.19 version ?

@GRASBOCK
Copy link

GRASBOCK commented Jun 1, 2022

It seems like WebSockets have been outsourced to other libraries. On this page they suggest to use reqwasm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment