diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index f75889ebc..efd534fe7 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -840,8 +840,11 @@ impl<'b> VirtualDom { .map(|path| path.len()); // if the path is 1 the attribute is in the root, so we don't need to clean it up // if the path is 0, the attribute is a not attached at all, so we don't need to clean it up - if let Some(..=1) = path_len { - continue; + + if let Some(len) = path_len { + if (..=1).contains(&len) { + continue; + } } let next_id = attr.mounted_element.get(); @@ -908,7 +911,13 @@ impl<'b> VirtualDom { match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } { RenderReturn::Ready(t) => self.remove_node(t, gen_muts), - _ => todo!("cannot handle nonstandard nodes"), + RenderReturn::Aborted(t) => { + if let Some(id) = t.id.get() { + self.try_reclaim(id); + } + return; + } + _ => todo!(), }; let props = self.scopes[scope.0].props.take(); diff --git a/packages/router/src/components/link.rs b/packages/router/src/components/link.rs index d077966eb..3ca0303c7 100644 --- a/packages/router/src/components/link.rs +++ b/packages/router/src/components/link.rs @@ -55,6 +55,9 @@ pub struct LinkProps<'a> { /// Pass children into the `` element pub children: Element<'a>, + + /// The onclick event handler. + pub onclick: Option>, } /// A component that renders a link to a route. @@ -119,7 +122,7 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element { title: format_args!("{}", title.unwrap_or("")), prevent_default: "{prevent_default}", target: format_args!("{}", if * new_tab { "_blank" } else { "" }), - onclick: move |_| { + onclick: move |evt| { log::trace!("Clicked link to {}", to); if !outerlink { @@ -138,6 +141,10 @@ pub fn Link<'a>(cx: Scope<'a, LinkProps<'a>>) -> Element { ); } } + + if let Some(onclick) = cx.props.onclick.as_ref() { + onclick.call(evt); + } }, children } diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index fdae04a9a..33d2c1b81 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -121,12 +121,10 @@ impl WebsysDom { } = attr { match namespace { - Some(ns) if *ns == "style" => el - .dyn_ref::() - .unwrap() - .style() - .set_property(name, value) - .unwrap(), + Some(ns) if *ns == "style" => { + el.dyn_ref::() + .map(|f| f.style().set_property(name, value)); + } Some(ns) => el.set_attribute_ns(Some(ns), name, value).unwrap(), None => el.set_attribute(name, value).unwrap(), } diff --git a/packages/web/src/hot_reload.rs b/packages/web/src/hot_reload.rs index 2c94d8cf3..cf73dc219 100644 --- a/packages/web/src/hot_reload.rs +++ b/packages/web/src/hot_reload.rs @@ -18,15 +18,15 @@ pub(crate) fn init() -> UnboundedReceiver> { #[cfg(debug_assertions)] pub(crate) fn init() -> UnboundedReceiver> { - use core::panic; use std::convert::TryInto; + use serde::Deserialize; + let window = web_sys::window().unwrap(); - let protocol = if window.location().protocol().unwrap() == "https:" { - "wss:" - } else { - "ws:" + let protocol = match window.location().protocol().unwrap() { + prot if prot == "https:" => "wss:", + _ => "ws:", }; let url = format!( @@ -43,10 +43,11 @@ pub(crate) fn init() -> UnboundedReceiver> { if let Ok(text) = e.data().dyn_into::() { let text: Result = text.try_into(); if let Ok(string) = text { - match serde_json::from_str(Box::leak(string.into_boxed_str())) { - Ok(template) => _ = tx.unbounded_send(template), - Err(e) => panic!("Failed to parse template: {}", e), - } + let val = serde_json::from_str::(&string).unwrap(); + // leak the value + let val: &'static serde_json::Value = Box::leak(Box::new(val)); + let template: Template<'_> = Template::deserialize(val).unwrap(); + tx.unbounded_send(template).unwrap(); } } }) as Box);