1
\$\begingroup\$

I wanted to render some Vega plots in a rust+wasm web application I've been building with Yew. I'm a bit new to Rust, so I'm looking for feedback on runtime safety and stylistic issues.

I was specially skeptical of the spawn_local I copied from someone's GitHub and the amount of unwraps thrown around.

use std::collections::HashMap;
use vega_lite_4::*;
use wasm_bindgen_futures::*;
use wasm_bindgen::prelude::*;
use yew::prelude::*;

#[wasm_bindgen]
extern {
    fn vegaEmbed(
        el: web_sys::Element,
        spec: JsValue,
        opts: JsValue,
    ) -> js_sys::Promise;
}

pub fn vega_embed(
    node_ref: &NodeRef,
    spec: &Vegalite,
    opts: &Option<HashMap<String, String>>,
) -> Result<(), Box<dyn std::error::Error>> {
    let el = node_ref.cast::<web_sys::Element>().unwrap();
    let spec = JsValue::from_serde(spec)?;
    let opts = match &opts {
        Some(x) => JsValue::from_serde(x)?,
        None => JsValue::from(js_sys::Object::new()),
    };
    let embed: JsFuture = vegaEmbed(el, spec, opts).into();
    spawn_local(async move { embed.await.unwrap(); });
    Ok(())
}

#[derive(Properties, Clone)]
pub struct Props {
    pub spec: Vegalite,
    pub opts: Option<HashMap<String, String>>,
}

pub struct VegaLiteChart {
    node_ref: NodeRef,
    spec: Vegalite,
    opts: Option<HashMap<String, String>>,
}

impl Component for VegaLiteChart {
    type Message = ();
    type Properties = Props;

    fn create(props: Self::Properties, _link: ComponentLink<Self>) -> Self {
        VegaLiteChart {
            node_ref: NodeRef::default(),
            spec: props.spec,
            opts: props.opts,
        }
    }

    fn view(&self) -> Html {
        html! { <div ref=self.node_ref.clone()></div> }
    }

    fn update(&mut self, _msg: Self::Message) -> ShouldRender {
        false
    }

    fn change(&mut self, _props: Self::Properties) -> ShouldRender {
        false
    }

    fn rendered(&mut self, _first_render: bool) {
        vega_embed(&self.node_ref, &self.spec, &self.opts).unwrap();
    }
}

```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.