diff --git a/packages/hooks/src/usestate.rs b/packages/hooks/src/usestate.rs index bce5b2b88..d77d7ceaa 100644 --- a/packages/hooks/src/usestate.rs +++ b/packages/hooks/src/usestate.rs @@ -39,16 +39,17 @@ pub fn use_state<'a, T: 'static>( let setter = Rc::new({ crate::to_owned![update_callback, slot]; move |new| { - let mut slot = slot.borrow_mut(); + { + let mut slot = slot.borrow_mut(); - // if there's only one reference (weak or otherwise), we can just swap the values - // Typically happens when the state is set multiple times - we don't want to create a new Rc for each new value - if let Some(val) = Rc::get_mut(&mut slot) { - *val = new; - } else { - *slot = Rc::new(new); + // if there's only one reference (weak or otherwise), we can just swap the values + // Typically happens when the state is set multiple times - we don't want to create a new Rc for each new value + if let Some(val) = Rc::get_mut(&mut slot) { + *val = new; + } else { + *slot = Rc::new(new); + } } - update_callback(); } }); @@ -92,7 +93,7 @@ impl UseState { /// } /// }) /// } - /// ``` + /// ``` #[must_use] pub fn current(&self) -> Rc { self.slot.borrow().clone() @@ -137,10 +138,10 @@ impl UseState { /// # use dioxus_hooks::*; /// fn component(cx: Scope) -> Element { /// let (value, set_value) = use_state(&cx, || 0); - /// + /// /// // to increment the value /// set_value.modify(|v| v + 1); - /// + /// /// // usage in async /// cx.spawn({ /// let set_value = set_value.to_owned(); @@ -153,8 +154,10 @@ impl UseState { /// } /// ``` pub fn modify(&self, f: impl FnOnce(&T) -> T) { - let current = self.slot.borrow(); - let new_val = f(current.as_ref()); + let new_val = { + let current = self.slot.borrow(); + f(current.as_ref()) + }; (self.setter)(new_val); } @@ -176,7 +179,7 @@ impl UseState { /// # use dioxus_hooks::*; /// fn component(cx: Scope) -> Element { /// let (value, set_value) = use_state(&cx, || 0); - /// + /// /// let as_rc = set_value.get(); /// assert_eq!(as_rc.as_ref(), &0); /// @@ -201,7 +204,7 @@ impl UseState { /// } /// }) /// } - /// ``` + /// ``` pub fn needs_update(&self) { (self.update_callback)(); } diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index ffbef9f4b..733e50e4b 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -28,17 +28,54 @@ impl WebsysDom { pub fn new(cfg: WebConfig, sender_callback: Rc) -> Self { // eventually, we just want to let the interpreter do all the work of decoding events into our event type let callback: Box = Box::new(move |event: &web_sys::Event| { - if let Ok(synthetic_event) = decode_trigger(event) { + let mut target = event + .target() + .expect("missing target") + .dyn_into::() + .expect("not a valid element"); + + let typ = event.type_(); + + let decoded: anyhow::Result = loop { + match target.get_attribute("data-dioxus-id").map(|f| f.parse()) { + Some(Ok(id)) => { + break Ok(UserEvent { + name: event_name_from_typ(&typ), + data: virtual_event_from_websys_event(event.clone()), + element: Some(ElementId(id)), + scope_id: None, + priority: dioxus_core::EventPriority::Medium, + }); + } + Some(Err(e)) => { + break Err(e.into()); + } + None => { + // walk the tree upwards until we actually find an event target + if let Some(parent) = target.parent_element() { + target = parent; + } else { + break Ok(UserEvent { + name: event_name_from_typ(&typ), + data: virtual_event_from_websys_event(event.clone()), + element: None, + scope_id: None, + priority: dioxus_core::EventPriority::Low, + }); + } + } + } + }; + + if let Ok(synthetic_event) = decoded { // Try to prevent default if the attribute is set - if let Some(target) = event.target() { - if let Some(node) = target.dyn_ref::() { - if let Some(name) = node.get_attribute("dioxus-prevent-default") { - if name == synthetic_event.name - || name.trim_start_matches("on") == synthetic_event.name - { - log::trace!("Preventing default"); - event.prevent_default(); - } + if let Some(node) = target.dyn_ref::() { + if let Some(name) = node.get_attribute("dioxus-prevent-default") { + if name == synthetic_event.name + || name.trim_start_matches("on") == synthetic_event.name + { + log::trace!("Preventing default"); + event.prevent_default(); } } } @@ -274,49 +311,6 @@ fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc anyhow::Result { - let mut target = event - .target() - .expect("missing target") - .dyn_into::() - .expect("not a valid element"); - - let typ = event.type_(); - - loop { - match target.get_attribute("data-dioxus-id").map(|f| f.parse()) { - Some(Ok(id)) => { - return Ok(UserEvent { - name: event_name_from_typ(&typ), - data: virtual_event_from_websys_event(event.clone()), - element: Some(ElementId(id)), - scope_id: None, - priority: dioxus_core::EventPriority::Medium, - }); - } - Some(Err(e)) => { - return Err(e.into()); - } - None => { - // walk the tree upwards until we actually find an event target - if let Some(parent) = target.parent_element() { - target = parent; - } else { - return Ok(UserEvent { - name: event_name_from_typ(&typ), - data: virtual_event_from_websys_event(event.clone()), - element: None, - scope_id: None, - priority: dioxus_core::EventPriority::Low, - }); - } - } - } - } -} - pub(crate) fn load_document() -> Document { web_sys::window() .expect("should have access to the Window")