Browse Source

Merge branch 'master' into jk/debugging-diff

Jonathan Kelley 3 years ago
parent
commit
1978f195b3
2 changed files with 66 additions and 69 deletions
  1. 19 16
      packages/hooks/src/usestate.rs
  2. 47 53
      packages/web/src/dom.rs

+ 19 - 16
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();
-
-                // 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);
+                {
+                    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);
+                    }
                 }
-
                 update_callback();
             }
         });
@@ -92,7 +93,7 @@ impl<T: 'static> UseState<T> {
     ///         }
     ///     })
     /// }
-    /// ```    
+    /// ```
     #[must_use]
     pub fn current(&self) -> Rc<T> {
         self.slot.borrow().clone()
@@ -137,10 +138,10 @@ impl<T: 'static> UseState<T> {
     /// # 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<T: 'static> UseState<T> {
     /// }
     /// ```
     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<T: 'static> UseState<T> {
     /// # 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<T: 'static> UseState<T> {
     ///         }
     ///     })
     /// }
-    /// ```   
+    /// ```
     pub fn needs_update(&self) {
         (self.update_callback)();
     }

+ 47 - 53
packages/web/src/dom.rs

@@ -28,17 +28,54 @@ impl WebsysDom {
     pub fn new(cfg: WebConfig, sender_callback: Rc<dyn Fn(SchedulerMsg)>) -> Self {
         // eventually, we just want to let the interpreter do all the work of decoding events into our event type
         let callback: Box<dyn FnMut(&Event)> = 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::<Element>()
+                .expect("not a valid element");
+
+            let typ = event.type_();
+
+            let decoded: anyhow::Result<UserEvent> = 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::<HtmlElement>() {
-                        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::<HtmlElement>() {
+                    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<dyn Any + Send
     }
 }
 
-/// This function decodes a websys event and produces an EventTrigger
-/// With the websys implementation, we attach a unique key to the nodes
-fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<UserEvent> {
-    let mut target = event
-        .target()
-        .expect("missing target")
-        .dyn_into::<Element>()
-        .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")