1
0
Эх сурвалжийг харах

Make cargo check --all --examples work!

Jonathan Kelley 1 жил өмнө
parent
commit
83bce6ce97
40 өөрчлөгдсөн 273 нэмэгдсэн , 377 устгасан
  1. 1 3
      Cargo.lock
  2. 2 2
      examples/custom_html.rs
  3. 1 1
      examples/file_explorer.rs
  4. 1 1
      examples/hello_world.rs
  5. 1 1
      examples/overlay.rs
  6. 1 1
      examples/pattern_model.rs
  7. 2 2
      examples/read_size.rs
  8. 1 1
      examples/window_focus.rs
  9. 1 1
      packages/desktop/Cargo.toml
  10. 2 4
      packages/desktop/examples/stress.rs
  11. 3 4
      packages/dioxus-tui/examples/all_terminal_events.rs
  12. 2 2
      packages/dioxus-tui/examples/border.rs
  13. 12 24
      packages/dioxus-tui/examples/buttons.rs
  14. 15 13
      packages/dioxus-tui/examples/colorpicker.rs
  15. 21 29
      packages/dioxus-tui/examples/hover.rs
  16. 21 32
      packages/dioxus-tui/examples/many_small_edit_stress.rs
  17. 9 18
      packages/dioxus-tui/examples/quadrants.rs
  18. 6 10
      packages/dioxus-tui/examples/task.rs
  19. 2 2
      packages/dioxus-tui/examples/text.rs
  20. 13 16
      packages/dioxus-tui/examples/widgets.rs
  21. 26 17
      packages/dioxus/src/launch.rs
  22. 2 1
      packages/liveview/Cargo.toml
  23. 3 3
      packages/liveview/_build.rs
  24. 5 8
      packages/liveview/examples/axum_stress.rs
  25. 1 1
      packages/native-core/examples/custom_attr.rs
  26. 1 1
      packages/native-core/examples/font_size.rs
  27. 1 1
      packages/native-core/examples/simple.rs
  28. 13 17
      packages/native-core/examples/simple_dioxus.rs
  29. 5 5
      packages/router/Cargo.toml
  30. 10 5
      packages/router/examples/simple_routes.rs
  31. 1 1
      packages/signals/Cargo.toml
  32. 7 11
      packages/signals/examples/context.rs
  33. 9 17
      packages/signals/examples/dependancies.rs
  34. 29 44
      packages/signals/examples/errors.rs
  35. 3 3
      packages/signals/examples/selector.rs
  36. 8 11
      packages/signals/examples/send.rs
  37. 18 53
      packages/signals/examples/split_subscriptions.rs
  38. 3 0
      packages/signals/src/signal.rs
  39. 1 1
      packages/web/examples/hydrate.rs
  40. 10 10
      packages/web/examples/timeout_count.rs

+ 1 - 3
Cargo.lock

@@ -2690,6 +2690,7 @@ version = "0.4.3"
 dependencies = [
  "async-trait",
  "axum 0.6.20",
+ "dioxus",
  "dioxus-core",
  "dioxus-hot-reload",
  "dioxus-html",
@@ -2806,14 +2807,12 @@ dependencies = [
  "criterion 0.5.1",
  "dioxus",
  "dioxus-cli-config",
- "dioxus-desktop",
  "dioxus-fullstack",
  "dioxus-lib",
  "dioxus-liveview",
  "dioxus-router",
  "dioxus-router-macro",
  "dioxus-ssr",
- "dioxus-web",
  "gloo",
  "gloo-utils",
  "js-sys",
@@ -2858,7 +2857,6 @@ version = "0.4.3"
 dependencies = [
  "dioxus",
  "dioxus-core",
- "dioxus-desktop",
  "futures-channel",
  "futures-util",
  "generational-box",

+ 2 - 2
examples/custom_html.rs

@@ -5,13 +5,13 @@ use dioxus::prelude::*;
 use dioxus_desktop::Config;
 
 fn main() {
-    LaunchBuilder::new()
+    LaunchBuilder::desktop()
         .with_cfg(
             Config::new().with_custom_head("<style>body { background-color: red; }</style>".into()),
         )
         .launch(app);
 
-    LaunchBuilder::new()
+    LaunchBuilder::desktop()
         .with_cfg(
             Config::new().with_custom_index(
                 r#"

+ 1 - 1
examples/file_explorer.rs

@@ -12,7 +12,7 @@ use dioxus::prelude::*;
 use dioxus_desktop::{Config, WindowBuilder};
 
 fn main() {
-    LaunchBuilder::new()
+    LaunchBuilder::desktop()
         .with_cfg(Config::new().with_window(WindowBuilder::new().with_resizable(true)))
         .launch(app)
 }

+ 1 - 1
examples/hello_world.rs

@@ -1,7 +1,7 @@
 use dioxus::prelude::*;
 
 fn main() {
-    launch_desktop(app);
+    launch(app);
 }
 
 fn app() -> Element {

+ 1 - 1
examples/overlay.rs

@@ -2,7 +2,7 @@ use dioxus::prelude::*;
 use dioxus_desktop::{tao::dpi::PhysicalPosition, LogicalSize, WindowBuilder};
 
 fn main() {
-    LaunchBuilder::new().with_cfg(make_config());
+    LaunchBuilder::desktop().with_cfg(make_config());
 }
 
 fn app() -> Element {

+ 1 - 1
examples/pattern_model.rs

@@ -32,7 +32,7 @@ fn main() {
             .with_inner_size(LogicalSize::new(320.0, 530.0)),
     );
 
-    LaunchBuilder::new().with_cfg(cfg).launch(app);
+    LaunchBuilder::desktop().with_cfg(cfg).launch(app);
 }
 
 const STYLE: &str = include_str!("./assets/calculator.css");

+ 2 - 2
examples/read_size.rs

@@ -4,8 +4,8 @@ use std::rc::Rc;
 use dioxus::{html::geometry::euclid::Rect, prelude::*};
 
 fn main() {
-    LaunchBuilder::new().with_cfg(
-        dioxus_desktop::Config::default().with_custom_head(
+    LaunchBuilder::desktop().with_cfg(
+        dioxus::desktop::Config::default().with_custom_head(
             r#"
 <style type="text/css">
     html, body {

+ 1 - 1
examples/window_focus.rs

@@ -5,7 +5,7 @@ use dioxus_desktop::use_wry_event_handler;
 use dioxus_desktop::{Config, WindowCloseBehaviour};
 
 fn main() {
-    LaunchBuilder::new()
+    LaunchBuilder::desktop()
         .with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
         .launch(app)
 }

+ 1 - 1
packages/desktop/Cargo.toml

@@ -79,7 +79,7 @@ default-features = false
 features = ["tokio_runtime", "hot-reload"]
 
 [dev-dependencies]
-dioxus = { workspace = true, features = ["launch", "desktop"]}
+dioxus = { workspace = true }
 exitcode = "1.1.2"
 
 [build-dependencies]

+ 2 - 4
packages/desktop/examples/stress.rs

@@ -12,9 +12,7 @@ fn app() -> Element {
 
     rsx! {
         button {
-            onclick: move |_| {
-                state.set(0);
-            },
+            onclick: move |_| state.set(0),
             "reset"
         }
         for _ in 0..10000 {
@@ -26,5 +24,5 @@ fn app() -> Element {
 }
 
 fn main() {
-    launch(app);
+    dioxus_desktop::launch::launch(app, Default::default(), Default::default());
 }

+ 3 - 4
packages/dioxus-tui/examples/all_terminal_events.rs

@@ -27,10 +27,11 @@ enum Event {
 const MAX_EVENTS: usize = 8;
 
 fn app() -> Element {
-    let events = use_signal(Vec::new);
+    let mut events = use_signal(Vec::new);
 
     let events_lock = events.read();
     let first_index = events_lock.len().saturating_sub(MAX_EVENTS);
+
     let events_rendered = events_lock[first_index..].iter().map(|event| {
         // TUI panics if text overflows (https://github.com/DioxusLabs/dioxus/issues/371)
         // temporary hack: just trim the strings (and make sure viewport is big enough)
@@ -40,9 +41,7 @@ fn app() -> Element {
         rsx!( p { "{trimmed}" } )
     });
 
-    let log_event = move |event: Event| {
-        events.write().push(event);
-    };
+    let mut log_event = move |event: Event| events.write().push(event);
 
     rsx! {
         div { width: "100%", height: "100%", flex_direction: "column",

+ 2 - 2
packages/dioxus-tui/examples/border.rs

@@ -5,7 +5,7 @@ fn main() {
 }
 
 fn app() -> Element {
-    let radius = use_signal(|| 0);
+    let mut radius = use_signal(|| 0);
 
     rsx! {
         div {
@@ -14,7 +14,7 @@ fn app() -> Element {
             justify_content: "center",
             align_items: "center",
             background_color: "hsl(248, 53%, 58%)",
-            onwheel: move |w| radius.modify(|r| (r + w.delta().strip_units().y as i8).abs()),
+            onwheel: move |w| radius.with_mut(|r| *r = (*r + w.delta().strip_units().y as i8).abs()),
 
             border_style: "solid none solid double",
             border_width: "thick",

+ 12 - 24
packages/dioxus-tui/examples/buttons.rs

@@ -5,19 +5,13 @@ fn main() {
     dioxus_tui::launch(app);
 }
 
-#[derive(PartialEq, Props)]
-struct ButtonProps {
-    color_offset: u32,
-    layer: u16,
-}
-
-#[allow(non_snake_case)]
-fn Button(cx: Scope<ButtonProps>) -> Element {
-    let toggle = use_signal(|| false);
-    let hovered = use_signal(|| false);
+#[component]
+fn Button(color_offset: u32, layer: u16) -> Element {
+    let mut toggle = use_signal(|| false);
+    let mut hovered = use_signal(|| false);
 
-    let hue = cx.props.color_offset % 255;
-    let saturation = if *toggle.get() { 50 } else { 25 } + if *hovered.get() { 50 } else { 25 };
+    let hue = color_offset % 255;
+    let saturation = if toggle() { 50 } else { 25 } + if hovered() { 50 } else { 25 };
     let brightness = saturation / 2;
     let color = format!("hsl({hue}, {saturation}, {brightness})");
 
@@ -26,26 +20,20 @@ fn Button(cx: Scope<ButtonProps>) -> Element {
             width: "100%",
             height: "100%",
             background_color: "{color}",
-            tabindex: "{cx.props.layer}",
+            tabindex: "{layer}",
             onkeydown: move |e| {
                 if let Code::Space = e.inner().code() {
-                    toggle.modify(|f| !f);
+                    toggle.toggle();
                 }
             },
-            onclick: move |_| {
-                toggle.modify(|f| !f);
-            },
-            onmouseenter: move |_| {
-                hovered.set(true);
-            },
-            onmouseleave: move |_|{
-                hovered.set(false);
-            },
+            onclick: move |_| toggle.toggle(),
+            onmouseenter: move |_| hovered.set(true),
+            onmouseleave: move |_| hovered.set(false),
             justify_content: "center",
             align_items: "center",
             display: "flex",
             flex_direction: "column",
-            p{ "tabindex: {cx.props.layer}" }
+            p { "tabindex: {layer}" }
         }
     }
 }

+ 15 - 13
packages/dioxus-tui/examples/colorpicker.rs

@@ -9,25 +9,27 @@ fn main() {
 }
 
 fn app() -> Element {
-    let hue = use_signal(|| 0.0);
-    let brightness = use_signal(|| 0.0);
-    let tui_query: Query = cx.consume_context().unwrap();
-    let mapping: DioxusElementToNodeId = cx.consume_context().unwrap();
+    let mut hue = use_signal(|| 0.0);
+    let mut brightness = use_signal(|| 0.0);
+    let tui_query: Query = consume_context();
+    let mapping: DioxusElementToNodeId = consume_context();
+
     // disable templates so that every node has an id and can be queried
     rsx! {
         div {
             width: "100%",
             background_color: "hsl({hue}, 70%, {brightness}%)",
             onmousemove: move |evt| {
-                if let RenderReturn::Ready(node) = cx.root_node() {
-                    if let Some(id) = node.root_ids.borrow().first().cloned() {
-                        let node = tui_query.get(mapping.get_node_id(id).unwrap());
-                        let Size { width, height } = node.size().unwrap();
-                        let pos = evt.inner().element_coordinates();
-                        hue.set((pos.x as f32 / width as f32) * 255.0);
-                        brightness.set((pos.y as f32 / height as f32) * 100.0);
-                    }
-                }
+                todo!()
+                // if let RenderReturn::Ready(node) = root_node() {
+                //     if let Some(id) = node.root_ids.borrow().first().cloned() {
+                //         let node = tui_query.get(mapping.get_node_id(id).unwrap());
+                //         let Size { width, height } = node.size().unwrap();
+                //         let pos = evt.inner().element_coordinates();
+                //         hue.set((pos.x as f32 / width as f32) * 255.0);
+                //         brightness.set((pos.y as f32 / height as f32) * 100.0);
+                //     }
+                // }
             },
             "hsl({hue}, 70%, {brightness}%)"
         }

+ 21 - 29
packages/dioxus-tui/examples/hover.rs

@@ -23,32 +23,24 @@ fn app() -> Element {
         127 * b
     }
 
-    let q1_color = use_signal(|| [200; 3]);
-    let q2_color = use_signal(|| [200; 3]);
-    let q3_color = use_signal(|| [200; 3]);
-    let q4_color = use_signal(|| [200; 3]);
+    let mut q1_color = use_signal(|| [200; 3]);
+    let mut q2_color = use_signal(|| [200; 3]);
+    let mut q3_color = use_signal(|| [200; 3]);
+    let mut q4_color = use_signal(|| [200; 3]);
 
-    let q1_color_str = to_str(q1_color);
-    let q2_color_str = to_str(q2_color);
-    let q3_color_str = to_str(q3_color);
-    let q4_color_str = to_str(q4_color);
+    let mut page_coordinates = use_signal(|| "".to_string());
+    let mut element_coordinates = use_signal(|| "".to_string());
+    let mut buttons = use_signal(|| "".to_string());
+    let mut modifiers = use_signal(|| "".to_string());
 
-    let page_coordinates = use_signal(|| "".to_string());
-    let element_coordinates = use_signal(|| "".to_string());
-    let buttons = use_signal(|| "".to_string());
-    let modifiers = use_signal(|| "".to_string());
-
-    let update_data = move |event: Event<MouseData>| {
-        let mouse_data = event.inner();
-
-        page_coordinates.set(format!("{:?}", mouse_data.page_coordinates()));
-        element_coordinates.set(format!("{:?}", mouse_data.element_coordinates()));
+    let mut update_data = move |event: Event<MouseData>| {
+        page_coordinates.set(format!("{:?}", event.page_coordinates()));
+        element_coordinates.set(format!("{:?}", event.element_coordinates()));
 
         // Note: client coordinates are also available, but they would be the same as the page coordinates in this example, because there is no scrolling.
         // There are also screen coordinates, but they are currently the same as client coordinates due to technical limitations
-
-        buttons.set(format!("{:?}", mouse_data.held_buttons()));
-        modifiers.set(format!("{:?}", mouse_data.modifiers()));
+        buttons.set(format!("{:?}", event.held_buttons()));
+        modifiers.set(format!("{:?}", event.modifiers()));
     };
 
     rsx! {
@@ -66,11 +58,11 @@ fn app() -> Element {
                     height: "100%",
                     justify_content: "center",
                     align_items: "center",
-                    background_color: "{q1_color_str}",
+                    background_color: to_str(&q1_color()),
                     onmouseenter: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
                     onmousedown: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
                     onmouseup: move |m| q1_color.set([get_brightness(m.inner()), 0, 0]),
-                    onwheel: move |w| q1_color.set([q1_color[0] + (10.0 * w.delta().strip_units().y) as i32, 0, 0]),
+                    onwheel: move |w| q1_color.set([q1_color()[0] + (10.0 * w.delta().strip_units().y) as i32, 0, 0]),
                     onmouseleave: move |_| q1_color.set([200; 3]),
                     onmousemove: update_data,
                     "click me"
@@ -80,11 +72,11 @@ fn app() -> Element {
                     height: "100%",
                     justify_content: "center",
                     align_items: "center",
-                    background_color: "{q2_color_str}",
+                    background_color: to_str(&q2_color()),
                     onmouseenter: move |m| q2_color.set([get_brightness(m.inner()); 3]),
                     onmousedown: move |m| q2_color.set([get_brightness(m.inner()); 3]),
                     onmouseup: move |m| q2_color.set([get_brightness(m.inner()); 3]),
-                    onwheel: move |w| q2_color.set([q2_color[0] + (10.0 * w.delta().strip_units().y) as i32; 3]),
+                    onwheel: move |w| q2_color.set([q2_color()[0] + (10.0 * w.delta().strip_units().y) as i32; 3]),
                     onmouseleave: move |_| q2_color.set([200; 3]),
                     onmousemove: update_data,
                     "click me"
@@ -100,11 +92,11 @@ fn app() -> Element {
                     height: "100%",
                     justify_content: "center",
                     align_items: "center",
-                    background_color: "{q3_color_str}",
+                    background_color: to_str(&q3_color()),
                     onmouseenter: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
                     onmousedown: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
                     onmouseup: move |m| q3_color.set([0, get_brightness(m.inner()), 0]),
-                    onwheel: move |w| q3_color.set([0, q3_color[1] + (10.0 * w.delta().strip_units().y) as i32, 0]),
+                    onwheel: move |w| q3_color.set([0, q3_color()[1] + (10.0 * w.delta().strip_units().y) as i32, 0]),
                     onmouseleave: move |_| q3_color.set([200; 3]),
                     onmousemove: update_data,
                     "click me"
@@ -114,11 +106,11 @@ fn app() -> Element {
                     height: "100%",
                     justify_content: "center",
                     align_items: "center",
-                    background_color: "{q4_color_str}",
+                    background_color: to_str(&q4_color()),
                     onmouseenter: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
                     onmousedown: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
                     onmouseup: move |m| q4_color.set([0, 0, get_brightness(m.inner())]),
-                    onwheel: move |w| q4_color.set([0, 0, q4_color[2] + (10.0 * w.delta().strip_units().y) as i32]),
+                    onwheel: move |w| q4_color.set([0, 0, q4_color()[2] + (10.0 * w.delta().strip_units().y) as i32]),
                     onmouseleave: move |_| q4_color.set([200; 3]),
                     onmousemove: update_data,
                     "click me"

+ 21 - 32
packages/dioxus-tui/examples/many_small_edit_stress.rs

@@ -5,28 +5,22 @@ use dioxus_tui::{Config, TuiContext};
 fn main() {
     for size in 1..=20usize {
         for _ in 0..10 {
-            dioxus_tui::launch_cfg_with_props(app, size, Config::default().with_headless())
+            todo!()
+            // dioxus_tui::launch_cfg(app, vec![size], Config::default().with_headless())
         }
     }
 }
 
-#[derive(Props, PartialEq)]
-struct BoxProps {
-    x: usize,
-    y: usize,
-    hue: f32,
-    alpha: f32,
-}
-#[allow(non_snake_case)]
-fn Box(cx: Scope<BoxProps>) -> Element {
+#[component]
+fn Box(x: usize, y: usize, hue: f32, alpha: f32) -> Element {
     let count = use_signal(|| 0);
 
-    let x = cx.props.x * 2;
-    let y = cx.props.y * 2;
-    let hue = cx.props.hue;
-    let display_hue = cx.props.hue as u32 / 10;
-    let count = count.get();
-    let alpha = cx.props.alpha + (count % 100) as f32;
+    let x = x * 2;
+    let y = y * 2;
+    let hue = hue;
+    let display_hue = hue as u32 / 10;
+
+    let alpha = alpha + (count() % 100) as f32;
 
     rsx! {
         div {
@@ -41,22 +35,19 @@ fn Box(cx: Scope<BoxProps>) -> Element {
     }
 }
 
-#[derive(Props, PartialEq)]
-struct GridProps {
-    size: usize,
-}
-#[allow(non_snake_case)]
-fn Grid(cx: Scope<GridProps>) -> Element {
-    let size = cx.props.size;
-    let count = use_signal(|| 0);
-    let counts = use_signal(|| vec![0; size * size]);
+#[component]
+fn Grid(size: usize) -> Element {
+    let size = size;
+    let mut count = use_signal(|| 0);
+    let mut counts = use_signal(|| vec![0; size * size]);
+
+    let ctx: TuiContext = consume_context();
 
-    let ctx: TuiContext = cx.consume_context().unwrap();
-    if *count.get() + 1 >= (size * size) {
+    if count() + 1 >= (size * size) {
         ctx.quit();
     } else {
         counts.with_mut(|c| {
-            let i = *count.current();
+            let i = count();
             c[i] += 1;
             c[i] %= 360;
         });
@@ -97,14 +88,12 @@ fn Grid(cx: Scope<GridProps>) -> Element {
     }
 }
 
-fn app(cx: Scope<usize>) -> Element {
+fn app(props: usize) -> Element {
     rsx! {
         div{
             width: "100%",
             height: "100%",
-            Grid{
-                size: *cx.props,
-            }
+            Grid{ size: props }
         }
     }
 }

+ 9 - 18
packages/dioxus-tui/examples/quadrants.rs

@@ -1,29 +1,22 @@
 #![allow(non_snake_case)]
 
 use dioxus::prelude::*;
-use dioxus_tui::Config;
 
 fn main() {
-    dioxus_tui::launch_cfg(app, Config::default());
+    dioxus_tui::launch_cfg(app, Default::default());
 }
 
-#[derive(Props, PartialEq)]
-struct QuadrentProps {
-    color: String,
-    text: String,
-}
-
-fn Quadrant(cx: Scope<QuadrentProps>) -> Element {
+#[component]
+fn Quadrant(color: String, text: String) -> Element {
     rsx! {
         div {
             border_width: "1px",
             width: "50%",
             height: "100%",
-            background_color: "{cx.props.color}",
             justify_content: "center",
             align_items: "center",
-
-            "{cx.props.text}"
+            background_color: "{color}",
+            "{text}"
         }
     }
 }
@@ -34,30 +27,28 @@ fn app() -> Element {
             width: "100%",
             height: "100%",
             flex_direction: "column",
-
             div {
                 width: "100%",
                 height: "50%",
                 flex_direction: "row",
-                Quadrant{
+                Quadrant {
                     color: "red".to_string(),
                     text: "[A]".to_string()
                 },
-                Quadrant{
+                Quadrant {
                     color: "black".to_string(),
                     text: "[B]".to_string()
                 }
             }
-
             div {
                 width: "100%",
                 height: "50%",
                 flex_direction: "row",
-                Quadrant{
+                Quadrant {
                     color: "green".to_string(),
                     text: "[C]".to_string()
                 },
-                Quadrant{
+                Quadrant {
                     color: "blue".to_string(),
                     text: "[D]".to_string()
                 }

+ 6 - 10
packages/dioxus-tui/examples/task.rs

@@ -5,17 +5,13 @@ fn main() {
 }
 
 fn app() -> Element {
-    let count = use_signal(|| 0);
+    let mut count = use_signal(|| 0);
 
-    use_future(move |_| {
-        let count = count.to_owned();
-        let update = cx.schedule_update();
-        async move {
-            loop {
-                count.with_mut(|f| *f += 1);
-                tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
-                update();
-            }
+    use_future(move || async move {
+        loop {
+            count += 1;
+            tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
+            schedule_update();
         }
     });
 

+ 2 - 2
packages/dioxus-tui/examples/text.rs

@@ -5,14 +5,14 @@ fn main() {
 }
 
 fn app() -> Element {
-    let alpha = use_signal(|| 100);
+    let mut alpha = use_signal(|| 100);
 
     rsx! {
         div {
             width: "100%",
             height: "100%",
             flex_direction: "column",
-            onwheel: move |evt| alpha.set((**alpha + evt.inner().delta().strip_units().y as i64).clamp(0, 100)),
+            onwheel: move |evt| alpha.set((alpha() + evt.inner().delta().strip_units().y as i64).clamp(0, 100)),
 
             p {
                 background_color: "black",

+ 13 - 16
packages/dioxus-tui/examples/widgets.rs

@@ -6,19 +6,18 @@ fn main() {
 }
 
 fn app() -> Element {
-    let bg_green = use_signal(|| false);
+    let mut bg_green = use_signal(|| false);
+    let color = if bg_green() { "green" } else { "red" };
 
-    let color = if *bg_green.get() { "green" } else { "red" };
     rsx! {
-        div{
+        div {
             width: "100%",
             background_color: "{color}",
             flex_direction: "column",
             align_items: "center",
             justify_content: "center",
-
             input {
-                oninput: |data| if &data.value()== "good"{
+                oninput: move |data| if data.value() == "good" {
                     bg_green.set(true);
                 } else{
                     bg_green.set(false);
@@ -30,9 +29,9 @@ fn app() -> Element {
                 checked: "true",
             }
             input {
-                oninput: |data| if &data.value()== "hello world"{
+                oninput: move |data| if &data.value() == "hello world"{
                     bg_green.set(true);
-                } else{
+                } else {
                     bg_green.set(false);
                 },
                 width: "50%",
@@ -40,7 +39,7 @@ fn app() -> Element {
                 maxlength: "11",
             }
             input {
-                oninput: |data| {
+                oninput: move |data| {
                     if (data.value().parse::<f32>().unwrap() - 40.0).abs() < 5.0 {
                         bg_green.set(true);
                     } else{
@@ -54,10 +53,10 @@ fn app() -> Element {
                 max: "80",
             }
             input {
-                oninput: |data| {
-                    if data.value()== "10"{
+                oninput: move |data| {
+                    if data.value() == "10"{
                         bg_green.set(true);
-                    } else{
+                    } else {
                         bg_green.set(false);
                     }
                 },
@@ -67,8 +66,8 @@ fn app() -> Element {
                 maxlength: "4",
             }
             input {
-                oninput: |data| {
-                    if data.value()== "hello world"{
+                oninput: move |data| {
+                    if data.value() == "hello world"{
                         bg_green.set(true);
                     } else{
                         bg_green.set(false);
@@ -80,9 +79,7 @@ fn app() -> Element {
                 maxlength: "11",
             }
             input {
-                oninput: |_| {
-                    bg_green.set(true)
-                },
+                oninput: move |_| { bg_green.set(true) },
                 r#type: "button",
                 value: "green",
                 width: "50%",

+ 26 - 17
packages/dioxus/src/launch.rs

@@ -68,7 +68,7 @@ impl LaunchBuilder {
 
     /// Launch your fullstack application.
     #[cfg(feature = "mobile")]
-    pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config> {
+    pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config, UnsendContext> {
         LaunchBuilder {
             launch_fn: dioxus_mobile::launch::launch,
             contexts: Vec::new(),
@@ -89,30 +89,40 @@ impl LaunchBuilder {
 }
 
 // Fullstack platform builder
-impl<Cfg: Default> LaunchBuilder<Cfg, ValidContext> {
+impl<Cfg> LaunchBuilder<Cfg, UnsendContext> {
+    /// Inject state into the root component's context that is created on the thread that the app is launched on.
+    pub fn with_context_provider(mut self, state: impl Fn() -> Box<dyn Any> + 'static) -> Self {
+        self.contexts.push(Box::new(state) as Box<UnsendContext>);
+        self
+    }
+
+    /// Inject state into the root component's context.
+    pub fn with_context(mut self, state: impl Any + Clone + 'static) -> Self {
+        self.contexts
+            .push(Box::new(move || Box::new(state.clone())));
+        self
+    }
+}
+
+impl<Cfg> LaunchBuilder<Cfg, SendContext> {
     /// Inject state into the root component's context that is created on the thread that the app is launched on.
     pub fn with_context_provider(
         mut self,
-
-        #[cfg(feature = "fullstack")] state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
-        #[cfg(not(feature = "fullstack"))] state: impl Fn() -> Box<dyn Any> + 'static,
+        state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
     ) -> Self {
-        self.contexts.push(Box::new(state) as Box<ValidContext>);
+        self.contexts.push(Box::new(state) as Box<SendContext>);
         self
     }
 
-    #[cfg(feature = "fullstack")]
     /// Inject state into the root component's context.
-    pub fn with_context(
-        mut self,
-        #[cfg(feature = "fullstack")] state: impl Any + Clone + Send + Sync + 'static,
-        #[cfg(not(feature = "fullstack"))] state: impl Any + Clone + 'static,
-    ) -> Self {
+    pub fn with_context(mut self, state: impl Any + Clone + Send + Sync + 'static) -> Self {
         self.contexts
             .push(Box::new(move || Box::new(state.clone())));
         self
     }
+}
 
+impl<Cfg: Default, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
     /// Provide a platform-specific config to the builder.
     pub fn with_cfg(mut self, config: impl Into<Option<Cfg>>) -> Self {
         if let Some(config) = config.into() {
@@ -121,10 +131,9 @@ impl<Cfg: Default> LaunchBuilder<Cfg, ValidContext> {
         self
     }
 
-    #[allow(clippy::unit_arg)]
-    /// Launch the app.
+    /// Launch your application.
     pub fn launch(self, app: fn() -> Element) {
-        (self.launch_fn)(app, self.contexts, self.platform_config.unwrap_or_default());
+        (self.launch_fn)(app, self.contexts, self.platform_config.unwrap_or_default())
     }
 }
 
@@ -151,13 +160,13 @@ pub fn launch(app: fn() -> Element) {
     LaunchBuilder::new().launch(app)
 }
 
-#[cfg(all(feature = "web", not(feature = "fullstack")))]
+#[cfg(all(feature = "web"))]
 /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
 pub fn launch_web(app: fn() -> Element) {
     LaunchBuilder::web().launch(app)
 }
 
-#[cfg(all(feature = "desktop", not(feature = "fullstack")))]
+#[cfg(all(feature = "desktop"))]
 /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
 pub fn launch_desktop(app: fn() -> Element) {
     LaunchBuilder::desktop().launch(app)

+ 2 - 1
packages/liveview/Cargo.toml

@@ -57,8 +57,9 @@ salvo = { version = "0.63.0", features = ["affix", "websocket"] }
 rocket = "0.5.0"
 rocket_ws = "0.1.0"
 tower = "0.4.13"
+dioxus = { workspace = true }
 
-# [build-dependencies]
+[build-dependencies]
 # dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] }
 # minify-js = "0.5.6"
 

+ 3 - 3
packages/liveview/_build.rs

@@ -12,10 +12,10 @@ fn main() {
               async function read_files() {
                 const files = target.files;
                 const file_contents = {};
-      
+
                 for (let i = 0; i < files.length; i++) {
                   const file = files[i];
-      
+
                   file_contents[file.name] = Array.from(
                     new Uint8Array(await file.arrayBuffer())
                   );
@@ -24,7 +24,7 @@ fn main() {
                   files: file_contents,
                 };
                 contents.files = file_engine;
-      
+
                 if (realId === null) {
                   return;
                 }

+ 5 - 8
packages/liveview/examples/axum_stress.rs

@@ -2,14 +2,11 @@ use axum::{extract::ws::WebSocketUpgrade, response::Html, routing::get, Router};
 use dioxus::prelude::*;
 
 fn app() -> Element {
-    let state = use_signal(|| 0);
-    use_future(|| {
-        to_owned![state];
-        async move {
-            loop {
-                state += 1;
-                tokio::time::sleep(std::time::Duration::from_millis(1)).await;
-            }
+    let mut state = use_signal(|| 0);
+    use_future(move || async move {
+        loop {
+            state += 1;
+            tokio::time::sleep(std::time::Duration::from_millis(1)).await;
         }
     });
 

+ 1 - 1
packages/native-core/examples/custom_attr.rs

@@ -227,5 +227,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 // wait 1 second
                 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
             }
-        }
+        })
 }

+ 1 - 1
packages/native-core/examples/font_size.rs

@@ -171,5 +171,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 // wait 1 second
                 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
             }
-        }
+        })
 }

+ 1 - 1
packages/native-core/examples/simple.rs

@@ -218,5 +218,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 // wait 1 second
                 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
             }
-        }
+        })
 }

+ 13 - 17
packages/native-core/examples/simple_dioxus.rs

@@ -167,31 +167,27 @@ impl State for Border {
 
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     fn app() -> Element {
-        let count = use_signal(|| 0);
+        let mut count = use_signal(|| 0);
 
-        use_future((count,), |(count,)| async move {
+        use_future(|| async move {
             loop {
                 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
-                count.set(*count + 1);
+                count += 1;
             }
         });
 
         rsx! {
-            div{
-                color: "red",
+            div { color: "red",
                 "{count}",
                 Comp {}
             }
-        })
+        }
     }
 
     fn Comp() -> Element {
         rsx! {
-            div{
-                border: "",
-                "hello world"
-            }
-        })
+            div { border: "", "hello world" }
+        }
     }
 
     // create the vdom, the real_dom, and the binding layer between them
@@ -203,9 +199,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     ]);
     let mut dioxus_intigration_state = DioxusState::create(&mut rdom);
 
-    let mutations = vdom.rebuild();
     // update the structure of the real_dom tree
-    dioxus_intigration_state.apply_mutations(&mut rdom, mutations);
+    let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
+    vdom.rebuild(&mut writer);
+
     let mut ctx = SendAnyMap::new();
     // set the font size to 3.3
     ctx.insert(FontSize(3.3));
@@ -222,10 +219,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 vdom.wait_for_work().await;
 
                 // get the mutations from the vdom
-                let mutations = vdom.render_immediate();
-
                 // update the structure of the real_dom tree
-                dioxus_intigration_state.apply_mutations(&mut rdom, mutations);
+                let mut writer = dioxus_intigration_state.create_mutation_writer(&mut rdom);
+                vdom.rebuild(&mut writer);
 
                 // update the state of the real_dom tree
                 let mut ctx = SendAnyMap::new();
@@ -245,5 +241,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                     println!("{indent}{id:?} {color:?} {size:?} {border:?} {node_type:?}");
                 });
             }
-        }
+        })
 }

+ 5 - 5
packages/router/Cargo.toml

@@ -41,8 +41,8 @@ fullstack = ["dioxus-fullstack"]
 
 [dev-dependencies]
 axum = { version = "0.6.1", features = ["ws"] }
-dioxus = { path = "../dioxus" }
-dioxus-liveview = { workspace = true, features = ["axum"] }
+dioxus = { workspace = true }
+# dioxus-liveview = { workspace = true, features = ["axum"] }
 dioxus-ssr = { path = "../ssr" }
 criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
 
@@ -55,12 +55,12 @@ name = "incremental"
 required-features = ["ssr"]
 harness = false
 
-[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
-dioxus-desktop = { path = "../desktop" }
+# [target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
+# dioxus-desktop = { path = "../desktop" }
 
 [target.'cfg(target_family = "wasm")'.dev-dependencies]
 console_error_panic_hook = "0.1.7"
 dioxus-router = { path = ".", features = ["web"] }
-dioxus-web = { workspace = true }
+# dioxus-web = { workspace = true }
 gloo = "0.8.0"
 wasm-bindgen-test = "0.3.33"

+ 10 - 5
packages/router/examples/simple_routes.rs

@@ -44,7 +44,11 @@ async fn main() {
 
 #[cfg(not(feature = "liveview"))]
 fn main() {
-    launch(Route::Home {})
+    launch(|| {
+        rsx! {
+            Router::<Route> {}
+        }
+    })
 }
 
 #[component]
@@ -66,8 +70,8 @@ fn Route1(user_id: usize, dynamic: usize, query: String, extra: String) -> Eleme
         }
         Link {
             to: Route::Route1 {
-                user_id: *user_id,
-                dynamic: *dynamic,
+                user_id,
+                dynamic,
                 query: String::new(),
                 extra: extra.clone() + ".",
             },
@@ -87,7 +91,7 @@ fn Route1(user_id: usize, dynamic: usize, query: String, extra: String) -> Eleme
 fn Route2(user_id: usize) -> Element {
     rsx! {
         pre { "Route2{{\n\tuser_id:{user_id}\n}}" }
-        {(0..*user_id).map(|i| rsx!{ p { "{i}" } })},
+        {(0..user_id).map(|i| rsx!{ p { "{i}" } })},
         p { "Footer" }
         Link {
             to: Route::Route3 {
@@ -100,8 +104,9 @@ fn Route2(user_id: usize) -> Element {
 
 #[component]
 fn Route3(dynamic: String) -> Element {
+    let mut current_route_str = use_signal(String::new);
+
     let current_route = use_route()?;
-    let current_route_str = use_signal(String::new);
     let parsed = Route::from_str(&current_route_str.read());
 
     let site_map = Route::SITE_MAP

+ 1 - 1
packages/signals/Cargo.toml

@@ -25,7 +25,7 @@ futures-util = { workspace = true }
 
 [dev-dependencies]
 dioxus = { workspace = true }
-dioxus-desktop = { workspace = true }
+# dioxus-desktop = { workspace = true }
 tokio = { version = "1", features = ["full"] }
 tracing-subscriber = "0.3.17"
 simple_logger = "4.2.0"

+ 7 - 11
packages/signals/examples/context.rs

@@ -4,22 +4,18 @@ use dioxus::prelude::*;
 use dioxus_signals::Signal;
 
 fn main() {
-    dioxus_desktop::launch(app);
+    // dioxus_desktop::launch(app);
 }
 
+// Because signal is never read in this component, this component will not rerun when the signal changes
 fn app() -> Element {
-    // Because signal is never read in this component, this component will not rerun when the signal changes
     use_context_provider(|| Signal::new(0));
-
-    rsx! {
-        Child {}
-    }
+    rsx! { Child {} }
 }
 
+// This component does read from the signal, so when the signal changes it will rerun
+#[component]
 fn Child() -> Element {
-    let signal: Signal<i32> = *use_context(cx).unwrap();
-    // This component does read from the signal, so when the signal changes it will rerun
-    rsx! {
-        "{signal}"
-    }
+    let signal: Signal<i32> = use_context();
+    rsx! { "{signal}" }
 }

+ 9 - 17
packages/signals/examples/dependancies.rs

@@ -1,37 +1,29 @@
-#![allow(non_snake_case)]
-
 use dioxus::prelude::*;
-use dioxus_signals::*;
 
 fn main() {
-    dioxus_desktop::launch(app);
+    // dioxus_desktop::launch(app);
 }
 
 fn app() -> Element {
-    let signal = use_signal(|| 0);
+    let mut signal = use_signal(|| 0);
 
     use_future(|| async move {
         loop {
             tokio::time::sleep(std::time::Duration::from_secs(1)).await;
-            *signal.write() += 1;
+            signal += 1;
         }
     });
 
-    let local_state = use_signal(|| 0);
-    let computed = use_selector_with_dependencies((local_state.get(),), move |(local_state,)| {
+    let mut local_state = use_signal(|| 0);
+
+    let computed = use_selector_with_dependencies((&local_state(),), move |(local_state,)| {
         local_state * 2 + signal.cloned()
     });
+
     println!("Running app");
 
     rsx! {
-        button {
-            onclick: move |_| {
-                local_state.set(local_state.get() + 1);
-            },
-            "Add one"
-        }
-        div {
-            "{computed}"
-        }
+        button { onclick: move |_| local_state.set(local_state() + 1), "Add one" }
+        div { "{computed}" }
     }
 }

+ 29 - 44
packages/signals/examples/errors.rs

@@ -1,11 +1,7 @@
-#![allow(non_snake_case)]
-
 use dioxus::prelude::*;
-use dioxus_signals::{use_signal, use_signal_sync, Signal};
-use generational_box::SyncStorage;
 
 fn main() {
-    dioxus_desktop::launch(app);
+    // dioxus_desktop::launch(app);
 }
 
 #[derive(Clone, Copy)]
@@ -15,34 +11,26 @@ enum ErrorComponent {
     ReadDropped,
 }
 
-fn app(cx: Scope) -> Element {
-    let error = use_signal(cx, || None);
+fn app() -> Element {
+    let mut error = use_signal(|| None as Option<ErrorComponent>);
 
     render! {
-        match *error() {
+        match error() {
             Some(ErrorComponent::Read) => render! { Read {} },
             Some(ErrorComponent::ReadMut) => render! { ReadMut {} },
             Some(ErrorComponent::ReadDropped) => render! { ReadDropped {} },
             None => render! {
-                button {
-                    onclick: move |_| error.set(Some(ErrorComponent::Read)),
-                    "Read"
-                }
-                button {
-                    onclick: move |_| error.set(Some(ErrorComponent::ReadMut)),
-                    "ReadMut"
-                }
-                button {
-                    onclick: move |_| error.set(Some(ErrorComponent::ReadDropped)),
-                    "ReadDropped"
-                }
+                button { onclick: move |_| error.set(Some(ErrorComponent::Read)), "Read" }
+                button { onclick: move |_| error.set(Some(ErrorComponent::ReadMut)), "ReadMut" }
+                button { onclick: move |_| error.set(Some(ErrorComponent::ReadDropped)), "ReadDropped"}
             }
         }
     }
 }
 
-fn Read(cx: Scope) -> Element {
-    let signal = use_signal_sync(cx, || 0);
+#[component]
+fn Read() -> Element {
+    let mut signal = use_signal_sync(|| 0);
 
     let _write = signal.write();
     let _read = signal.read();
@@ -50,8 +38,9 @@ fn Read(cx: Scope) -> Element {
     todo!()
 }
 
-fn ReadMut(cx: Scope) -> Element {
-    let signal = use_signal_sync(cx, || 0);
+#[component]
+fn ReadMut() -> Element {
+    let mut signal = use_signal_sync(|| 0);
 
     let _read = signal.read();
     let _write = signal.write();
@@ -59,32 +48,28 @@ fn ReadMut(cx: Scope) -> Element {
     todo!()
 }
 
-fn ReadDropped(cx: Scope) -> Element {
-    let signal = use_signal_sync(cx, || None);
-    if cx.generation() < 4 {
-        cx.needs_update();
+#[component]
+fn ReadDropped() -> Element {
+    let signal = use_signal_sync(|| None as Option<SyncSignal<i32>>);
+
+    if generation() < 4 {
+        needs_update();
     }
+
     render! {
-        if let Some(value) = &*signal() {
-            render!{"{value:?}"}
+        if let Some(value) = signal() {
+            "{value:?}"
         } else {
-            render! {
-                ReadDroppedSignalChild { parent_signal: signal }
-            }
+            ReadDroppedSignalChild { parent_signal: signal }
         }
     }
 }
 
 #[component]
-fn ReadDroppedSignalChild(
-    cx: Scope,
-    parent_signal: Signal<Option<Signal<i32, SyncStorage>>, SyncStorage>,
-) -> Element {
-    let signal = use_signal_sync(cx, || 0);
-    cx.use_hook(move || {
-        parent_signal.set(Some(signal));
-    });
-    render! {
-        "{signal}"
-    }
+fn ReadDroppedSignalChild(parent_signal: SyncSignal<Option<SyncSignal<i32>>>) -> Element {
+    let signal = use_signal_sync(|| 0);
+
+    use_hook(move || parent_signal.set(Some(signal)));
+
+    render! { "{signal}" }
 }

+ 3 - 3
packages/signals/examples/selector.rs

@@ -2,17 +2,17 @@ use dioxus::prelude::*;
 use dioxus_signals::*;
 
 fn main() {
-    dioxus_desktop::launch(App);
+    // dioxus_desktop::launch(App);
 }
 
 #[component]
 fn App() -> Element {
-    let signal = use_signal(|| 0);
+    let mut signal = use_signal(|| 0);
     let doubled = use_selector(move || signal * 2);
 
     rsx! {
         button {
-            onclick: move |_| *signal.write() += 1,
+            onclick: move |_| signal += 1,
             "Increase"
         }
         Child { signal: doubled }

+ 8 - 11
packages/signals/examples/send.rs

@@ -2,25 +2,22 @@ use dioxus::prelude::*;
 use dioxus_signals::*;
 
 fn main() {
-    tracing_subscriber::fmt::init();
-    dioxus_desktop::launch(App);
+    // dioxus_desktop::launch(App);
 }
 
 #[component]
-fn App(cx: Scope) -> Element {
-    let mut signal = use_signal_sync(cx, || 0);
-    cx.use_hook(|| {
+fn App() -> Element {
+    let mut signal = use_signal_sync(|| 0);
+
+    use_hook(|| {
         std::thread::spawn(move || loop {
             std::thread::sleep(std::time::Duration::from_secs(1));
             signal += 1;
-        })
+        });
     });
 
-    render! {
-        button {
-            onclick: move |_| signal += 1,
-            "Increase"
-        }
+    rsx! {
+        button { onclick: move |_| signal += 1, "Increase" }
         "{signal}"
     }
 }

+ 18 - 53
packages/signals/examples/split_subscriptions.rs

@@ -4,7 +4,7 @@ use dioxus::prelude::*;
 use dioxus_signals::Signal;
 
 fn main() {
-    dioxus_desktop::launch(app);
+    // dioxus_desktop::launch(app);
 }
 
 #[derive(Clone, Copy, Default)]
@@ -14,10 +14,6 @@ struct ApplicationData {
     many_signals: Signal<Vec<Signal<i32>>>,
 }
 
-fn use_app_data() -> ApplicationData {
-    *use_context(cx).unwrap()
-}
-
 fn app() -> Element {
     use_context_provider(ApplicationData::default);
 
@@ -28,9 +24,10 @@ fn app() -> Element {
     }
 }
 
+#[component]
 fn ReadsFirst() -> Element {
     println!("running first");
-    let data = use_app_data(cx);
+    let mut data = use_context::<ApplicationData>();
 
     rsx! {
         button {
@@ -55,54 +52,37 @@ fn ReadsFirst() -> Element {
     }
 }
 
+#[component]
 fn ReadsSecond() -> Element {
     println!("running second");
-    let data = use_app_data(cx);
+    let mut data = use_context::<ApplicationData>();
 
     rsx! {
-        button {
-            onclick: move |_| {
-                *data.second_data.write() += 1;
-            },
-            "Increase"
-        }
-        button {
-            onclick: move |_| {
-                *data.second_data.write() -= 1;
-            },
-            "Decrease"
-        }
-        button {
-            onclick: move |_| {
-                *data.second_data.write() = 0;
-            },
-            "Reset"
-        }
+        button { onclick: move |_| data.second_data += 1, "Increase" }
+        button { onclick: move |_| data.second_data -= 1, "Decrease" }
+        button { onclick: move |_| data.second_data.set(0), "Reset" }
         "{data.second_data}"
     }
 }
 
+#[component]
 fn ReadsManySignals() -> Element {
     println!("running many signals");
-    let data = use_app_data(cx);
+    let mut data = use_context::<ApplicationData>();
 
     rsx! {
         button {
-            onclick: move |_| {
-                data.many_signals.write().push(Signal::new(0));
-            },
+            onclick: move |_| data.many_signals.write().push(Signal::new(0)),
             "Create"
         }
         button {
-            onclick: move |_| {
-                data.many_signals.write().pop();
-            },
+            onclick: move |_| { data.many_signals.write().pop(); },
             "Destroy"
         }
         button {
             onclick: move |_| {
-                if let Some(first) = data.many_signals.read().first() {
-                    *first.write() += 1;
+                if let Some(mut first) = data.many_signals.read().first().cloned() {
+                    first += 1;
                 }
             },
             "Increase First Item"
@@ -113,30 +93,15 @@ fn ReadsManySignals() -> Element {
     }
 }
 
-#[derive(Props, PartialEq)]
-struct ChildProps {
-    count: Signal<i32>,
-}
-
-fn Child(cx: Scope<ChildProps>) -> Element {
+#[component]
+fn Child(mut count: Signal<i32>) -> Element {
     println!("running child");
-    let count = cx.props.count;
 
     rsx! {
         div {
             "Child: {count}"
-            button {
-                onclick: move |_| {
-                    *count.write() += 1;
-                },
-                "Increase"
-            }
-            button {
-                onclick: move |_| {
-                    *count.write() -= 1;
-                },
-                "Decrease"
-            }
+            button { onclick: move |_| count += 1, "Increase" }
+            button { onclick: move |_| count -= 1, "Decrease" }
         }
     }
 }

+ 3 - 0
packages/signals/src/signal.rs

@@ -194,6 +194,9 @@ pub struct Signal<T: 'static, S: Storage<SignalData<T>> = UnsyncStorage> {
     pub(crate) inner: CopyValue<SignalData<T>, S>,
 }
 
+/// A signal that can safely shared between threads.
+pub type SyncSignal<T> = Signal<T, SyncStorage>;
+
 #[cfg(feature = "serde")]
 impl<T: serde::Serialize + 'static> serde::Serialize for Signal<T> {
     fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {

+ 1 - 1
packages/web/examples/hydrate.rs

@@ -53,5 +53,5 @@ fn main() {
         .set_inner_html(&pre);
 
     // now rehydrate
-    dioxus_web::launch_with_props(app, (), Config::new().hydrate(true));
+    dioxus_web::launch::launch(app, vec![], Config::new().hydrate(true));
 }

+ 10 - 10
packages/web/examples/timeout_count.rs

@@ -2,17 +2,16 @@
 use dioxus::prelude::*;
 
 fn main() {
-    dioxus_web::launch(app);
+    dioxus_web::launch::launch(app, vec![], Default::default());
 }
 
 fn app() -> Element {
-    let count = use_signal(|| 0);
-    let started = use_signal(|| false);
+    let mut count = use_signal(|| 0);
+    let mut started = use_signal(|| false);
 
-    let start = move || {
-        if !*started.get() {
-            let count = count.clone(); // clone reference rather than value
-            let alert = move || gloo_dialogs::alert(&format!("Your score was {}!", count.read()));
+    let mut start = move || {
+        if !started() {
+            let alert = move || gloo_dialogs::alert(&format!("Your score was {count}!",));
             gloo_timers::callback::Timeout::new(5_000, alert).forget();
         }
         started.set(true); // this cannot be done inside condition or infinite loop
@@ -22,10 +21,11 @@ fn app() -> Element {
         button {
             onclick: move |_event| {
                 start();
-                *count.write() += 1;
+                count += 1;
             },
-            if **started {
-                "Current score: {count.read()}"
+
+            if started() {
+                "Current score: {count}"
             } else {
                 "Start"
             }