Преглед на файлове

Fix flakey windows tests (#2332)

Evan Almloff преди 1 година
родител
ревизия
5ce91e1bfc

+ 3 - 0
Cargo.lock

@@ -2371,6 +2371,7 @@ dependencies = [
  "base64 0.21.7",
  "base64 0.21.7",
  "bytes",
  "bytes",
  "ciborium",
  "ciborium",
+ "dioxus",
  "dioxus-cli-config",
  "dioxus-cli-config",
  "dioxus-desktop",
  "dioxus-desktop",
  "dioxus-hot-reload",
  "dioxus-hot-reload",
@@ -2488,6 +2489,7 @@ dependencies = [
 name = "dioxus-lib"
 name = "dioxus-lib"
 version = "0.5.2"
 version = "0.5.2"
 dependencies = [
 dependencies = [
+ "dioxus",
  "dioxus-config-macro",
  "dioxus-config-macro",
  "dioxus-core 0.5.2",
  "dioxus-core 0.5.2",
  "dioxus-core-macro",
  "dioxus-core-macro",
@@ -2603,6 +2605,7 @@ dependencies = [
 name = "dioxus-router-macro"
 name = "dioxus-router-macro"
 version = "0.5.2"
 version = "0.5.2"
 dependencies = [
 dependencies = [
+ "dioxus",
  "proc-macro2",
  "proc-macro2",
  "quote",
  "quote",
  "slab",
  "slab",

+ 12 - 3
Makefile.toml

@@ -88,7 +88,7 @@ command = "cargo"
 args = ["build"]
 args = ["build"]
 
 
 [tasks.test-flow]
 [tasks.test-flow]
-dependencies = ["test"]
+dependencies = ["test", "docs"]
 private = true
 private = true
 
 
 [tasks.test]
 [tasks.test]
@@ -101,8 +101,7 @@ args = [
   "--tests",
   "--tests",
   "--examples",
   "--examples",
   "--workspace",
   "--workspace",
-  "--exclude",
-  "dioxus-router",
+  # These tests run on Ubuntu without a screen. Desktop tests that require a screen fail, so we skip them
   "--exclude",
   "--exclude",
   "dioxus-desktop",
   "dioxus-desktop",
   "--exclude",
   "--exclude",
@@ -110,6 +109,16 @@ args = [
 ]
 ]
 private = true
 private = true
 
 
+[tasks.docs]
+dependencies = ["build"]
+command = "cargo"
+args = [
+  "test",
+  "--doc",
+  "--workspace",
+]
+private = true
+
 [tasks.test-with-browser]
 [tasks.test-with-browser]
 env = { CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS = [
 env = { CARGO_MAKE_WORKSPACE_INCLUDE_MEMBERS = [
   "**/packages/router",
   "**/packages/router",

+ 43 - 36
examples/todomvc.rs

@@ -1,7 +1,6 @@
 //! The typical TodoMVC app, implemented in Dioxus.
 //! The typical TodoMVC app, implemented in Dioxus.
 
 
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_elements::input_data::keyboard_types::Key;
 use std::collections::HashMap;
 use std::collections::HashMap;
 
 
 fn main() {
 fn main() {
@@ -74,7 +73,7 @@ fn app() -> Element {
                         class: "toggle-all",
                         class: "toggle-all",
                         r#type: "checkbox",
                         r#type: "checkbox",
                         onchange: toggle_all,
                         onchange: toggle_all,
-                        checked: active_todo_count() == 0,
+                        checked: active_todo_count() == 0
                     }
                     }
                     label { r#for: "toggle-all" }
                     label { r#for: "toggle-all" }
                 }
                 }
@@ -98,8 +97,14 @@ fn app() -> Element {
         // A simple info footer
         // A simple info footer
         footer { class: "info",
         footer { class: "info",
             p { "Double-click to edit a todo" }
             p { "Double-click to edit a todo" }
-            p { "Created by " a { href: "http://github.com/jkelleyrtp/", "jkelleyrtp" } }
-            p { "Part of " a { href: "http://todomvc.com", "TodoMVC" } }
+            p {
+                "Created by "
+                a { href: "http://github.com/jkelleyrtp/", "jkelleyrtp" }
+            }
+            p {
+                "Part of "
+                a { href: "http://todomvc.com", "TodoMVC" }
+            }
         }
         }
     }
     }
 }
 }
@@ -132,7 +137,7 @@ fn TodoHeader(mut todos: Signal<HashMap<u32, TodoItem>>) -> Element {
                 value: "{draft}",
                 value: "{draft}",
                 autofocus: "true",
                 autofocus: "true",
                 oninput: move |evt| draft.set(evt.value()),
                 oninput: move |evt| draft.set(evt.value()),
-                onkeydown,
+                onkeydown
             }
             }
         }
         }
     }
     }
@@ -165,7 +170,7 @@ fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
                     r#type: "checkbox",
                     r#type: "checkbox",
                     id: "cbg-{id}",
                     id: "cbg-{id}",
                     checked: "{checked}",
                     checked: "{checked}",
-                    oninput: move |evt| todos.write().get_mut(&id).unwrap().checked = evt.checked(),
+                    oninput: move |evt| todos.write().get_mut(&id).unwrap().checked = evt.checked()
                 }
                 }
                 label {
                 label {
                     r#for: "cbg-{id}",
                     r#for: "cbg-{id}",
@@ -175,7 +180,9 @@ fn TodoEntry(mut todos: Signal<HashMap<u32, TodoItem>>, id: u32) -> Element {
                 }
                 }
                 button {
                 button {
                     class: "destroy",
                     class: "destroy",
-                    onclick: move |_| { todos.write().remove(&id); },
+                    onclick: move |_| {
+                        todos.write().remove(&id);
+                    },
                     prevent_default: "onclick"
                     prevent_default: "onclick"
                 }
                 }
             }
             }
@@ -211,41 +218,41 @@ fn ListFooter(
     let show_clear_completed = use_memo(move || todos.read().values().any(|todo| todo.checked));
     let show_clear_completed = use_memo(move || todos.read().values().any(|todo| todo.checked));
 
 
     rsx! {
     rsx! {
-        footer { class: "footer",
-            span { class: "todo-count",
-                strong { "{active_todo_count} " }
-                span {
-                    match active_todo_count() {
-                        1 => "item",
-                        _ => "items",
+            footer { class: "footer",
+                span { class: "todo-count",
+                    strong { "{active_todo_count} " }
+                    span {
+                        match active_todo_count() {
+                            1 => "item",
+                            _ => "items",
+                        },
+                        " left"
                     }
                     }
-                    " left"
                 }
                 }
-            }
-            ul { class: "filters",
-                for (state , state_text , url) in [
-                    (FilterState::All, "All", "#/"),
-                    (FilterState::Active, "Active", "#/active"),
-                    (FilterState::Completed, "Completed", "#/completed"),
-                ] {
-                    li {
-                        a {
-                            href: url,
-                            class: if filter() == state { "selected" },
-                            onclick: move |_| filter.set(state),
-                            prevent_default: "onclick",
-                            {state_text}
+                ul { class: "filters",
+                    for (state , state_text , url) in [
+        (FilterState::All, "All", "#/"),
+        (FilterState::Active, "Active", "#/active"),
+        (FilterState::Completed, "Completed", "#/completed"),
+    ] {
+                        li {
+                            a {
+                                href: url,
+                                class: if filter() == state { "selected" },
+                                onclick: move |_| filter.set(state),
+                                prevent_default: "onclick",
+                                {state_text}
+                            }
                         }
                         }
                     }
                     }
                 }
                 }
-            }
-            if show_clear_completed() {
-                button {
-                    class: "clear-completed",
-                    onclick: move |_| todos.write().retain(|_, todo| !todo.checked),
-                    "Clear completed"
+                if show_clear_completed() {
+                    button {
+                        class: "clear-completed",
+                        onclick: move |_| todos.write().retain(|_, todo| !todo.checked),
+                        "Clear completed"
+                    }
                 }
                 }
             }
             }
         }
         }
-    }
 }
 }

+ 1 - 1
packages/core/src/global_context.rs

@@ -145,7 +145,7 @@ pub fn remove_future(id: Task) {
 ///
 ///
 /// pub fn use_custom_state() -> CustomState {
 /// pub fn use_custom_state() -> CustomState {
 ///     use_hook(|| CustomState {
 ///     use_hook(|| CustomState {
-///         inner: Signal::new(InnerCustomState)
+///         inner: Signal::new(InnerCustomState(0))
 ///     })
 ///     })
 /// }
 /// }
 /// ```
 /// ```

+ 1 - 1
packages/core/src/scope_context.rs

@@ -310,7 +310,7 @@ impl Scope {
     ///
     ///
     /// pub fn use_custom_state() -> CustomState {
     /// pub fn use_custom_state() -> CustomState {
     ///     use_hook(|| CustomState {
     ///     use_hook(|| CustomState {
-    ///         inner: Signal::new(InnerCustomState)
+    ///         inner: Signal::new(InnerCustomState(0))
     ///     })
     ///     })
     /// }
     /// }
     /// ```
     /// ```

+ 4 - 6
packages/core/src/virtual_dom.rs

@@ -138,7 +138,7 @@ use tracing::instrument;
 ///
 ///
 /// let dom = VirtualDom::new(app);
 /// let dom = VirtualDom::new(app);
 ///
 ///
-/// real_dom.apply(dom.rebuild());
+/// dom.rebuild(real_dom.apply());
 ///
 ///
 /// loop {
 /// loop {
 ///     select! {
 ///     select! {
@@ -258,7 +258,7 @@ impl VirtualDom {
     ///
     ///
     /// ```rust, ignore
     /// ```rust, ignore
     /// let mut dom = VirtualDom::new_with_props(Example, SomeProps { name: "jane" });
     /// let mut dom = VirtualDom::new_with_props(Example, SomeProps { name: "jane" });
-    /// let mutations = dom.rebuild();
+    /// dom.rebuild_in_place();
     /// ```
     /// ```
     pub fn new_with_props<P: Clone + 'static, M: 'static>(
     pub fn new_with_props<P: Clone + 'static, M: 'static>(
         root: impl ComponentFunction<P, M>,
         root: impl ComponentFunction<P, M>,
@@ -302,7 +302,7 @@ impl VirtualDom {
     ///
     ///
     /// ```rust, ignore
     /// ```rust, ignore
     /// let mut dom = VirtualDom::new_from_root(VComponent::new(Example, SomeProps { name: "jane" }, "Example"));
     /// let mut dom = VirtualDom::new_from_root(VComponent::new(Example, SomeProps { name: "jane" }, "Example"));
-    /// let mutations = dom.rebuild();
+    /// dom.rebuild(to_writer);
     /// ```
     /// ```
     #[instrument(skip(root), level = "trace", name = "VirtualDom::new")]
     #[instrument(skip(root), level = "trace", name = "VirtualDom::new")]
     pub(crate) fn new_with_component(root: impl AnyProps + 'static) -> Self {
     pub(crate) fn new_with_component(root: impl AnyProps + 'static) -> Self {
@@ -611,9 +611,7 @@ impl VirtualDom {
     /// static app: Component = |cx|  rsx!{ "hello world" };
     /// static app: Component = |cx|  rsx!{ "hello world" };
     ///
     ///
     /// let mut dom = VirtualDom::new();
     /// let mut dom = VirtualDom::new();
-    /// let edits = dom.rebuild();
-    ///
-    /// apply_edits(edits);
+    /// dom.rebuild(to_writer);
     /// ```
     /// ```
     #[instrument(skip(self, to), level = "trace", name = "VirtualDom::rebuild")]
     #[instrument(skip(self, to), level = "trace", name = "VirtualDom::rebuild")]
     pub fn rebuild(&mut self, to: &mut impl WriteMutations) {
     pub fn rebuild(&mut self, to: &mut impl WriteMutations) {

+ 0 - 1
packages/core/tests/miri_full_app.rs

@@ -1,4 +1,3 @@
-use crate::dioxus_elements::SerializedMouseData;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 use dioxus_core::ElementId;
 use dioxus_core::ElementId;
 use dioxus_elements::SerializedHtmlEventConverter;
 use dioxus_elements::SerializedHtmlEventConverter;

+ 4 - 2
packages/core/tests/task.rs

@@ -66,7 +66,7 @@ async fn spawn_forever_persists() {
     #[component]
     #[component]
     fn Child() -> Element {
     fn Child() -> Element {
         spawn_forever(async move {
         spawn_forever(async move {
-            loop {
+            for _ in 0..10 {
                 POLL_COUNT.fetch_add(1, Ordering::Relaxed);
                 POLL_COUNT.fetch_add(1, Ordering::Relaxed);
                 tokio::time::sleep(Duration::from_millis(50)).await;
                 tokio::time::sleep(Duration::from_millis(50)).await;
             }
             }
@@ -82,7 +82,9 @@ async fn spawn_forever_persists() {
 
 
     tokio::select! {
     tokio::select! {
         _ = dom.wait_for_work() => {}
         _ = dom.wait_for_work() => {}
-        _ = tokio::time::sleep(Duration::from_millis(500)) => {}
+        // We intentionally wait a bit longer than 50ms*10 to make sure the test has time to finish
+        // Without the extra time, the test can fail on windows
+        _ = tokio::time::sleep(Duration::from_millis(1000)) => {}
     };
     };
 
 
     // By the time the tasks are finished, we should've accumulated ticks from two tasks
     // By the time the tasks are finished, we should've accumulated ticks from two tasks

+ 29 - 13
packages/desktop/headless_tests/events.rs

@@ -2,7 +2,6 @@ use std::collections::HashMap;
 
 
 use dioxus::html::geometry::euclid::Vector3D;
 use dioxus::html::geometry::euclid::Vector3D;
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_core::prelude::consume_context;
 use dioxus_desktop::DesktopContext;
 use dioxus_desktop::DesktopContext;
 
 
 #[path = "./utils.rs"]
 #[path = "./utils.rs"]
@@ -179,7 +178,10 @@ fn test_mouse_dblclick_div() -> Element {
                 println!("{:?}", event.data);
                 println!("{:?}", event.data);
                 assert!(event.data.modifiers().is_empty());
                 assert!(event.data.modifiers().is_empty());
                 assert!(
                 assert!(
-                    event.data.held_buttons().contains(dioxus_html::input_data::MouseButton::Primary),
+                    event
+                        .data
+                        .held_buttons()
+                        .contains(dioxus_html::input_data::MouseButton::Primary),
                 );
                 );
                 assert!(
                 assert!(
                     event
                     event
@@ -282,7 +284,8 @@ fn test_mouse_scroll_div() -> Element {
             onwheel: move |event| {
             onwheel: move |event| {
                 println!("{:?}", event.data);
                 println!("{:?}", event.data);
                 let dioxus_html::geometry::WheelDelta::Pixels(delta) = event.data.delta() else {
                 let dioxus_html::geometry::WheelDelta::Pixels(delta) = event.data.delta() else {
-                panic!("Expected delta to be in pixels") };
+                    panic!("Expected delta to be in pixels")
+                };
                 assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0));
                 assert_eq!(delta, Vector3D::new(1.0, 2.0, 3.0));
                 RECEIVED_EVENTS.with_mut(|x| *x += 1);
                 RECEIVED_EVENTS.with_mut(|x| *x += 1);
             }
             }
@@ -476,11 +479,16 @@ fn test_form_input() -> Element {
                     r#type: "text",
                     r#type: "text",
                     name: "username",
                     name: "username",
                     id: "form-username",
                     id: "form-username",
-                    oninput: set_username,
+                    oninput: set_username
                 }
                 }
                 input { r#type: "text", name: "full-name", value: "lorem" }
                 input { r#type: "text", name: "full-name", value: "lorem" }
                 input { r#type: "password", name: "password", value: "ipsum" }
                 input { r#type: "password", name: "password", value: "ipsum" }
-                input { r#type: "radio", name: "color", value: "red", checked: true }
+                input {
+                    r#type: "radio",
+                    name: "color",
+                    value: "red",
+                    checked: true
+                }
                 input { r#type: "radio", name: "color", value: "blue" }
                 input { r#type: "radio", name: "color", value: "blue" }
                 button { r#type: "submit", value: "Submit", "Submit the form" }
                 button { r#type: "submit", value: "Submit", "Submit the form" }
             }
             }
@@ -511,13 +519,21 @@ fn test_form_submit() -> Element {
     rsx! {
     rsx! {
         div {
         div {
             h1 { "Form" }
             h1 { "Form" }
-            form {
-                id: "form-submitter",
-                onsubmit: set_values,
-                input { r#type: "text", name: "username", id: "username", value: "goodbye" }
+            form { id: "form-submitter", onsubmit: set_values,
+                input {
+                    r#type: "text",
+                    name: "username",
+                    id: "username",
+                    value: "goodbye"
+                }
                 input { r#type: "text", name: "full-name", value: "lorem" }
                 input { r#type: "text", name: "full-name", value: "lorem" }
                 input { r#type: "password", name: "password", value: "ipsum" }
                 input { r#type: "password", name: "password", value: "ipsum" }
-                input { r#type: "radio", name: "color", value: "red", checked: true }
+                input {
+                    r#type: "radio",
+                    name: "color",
+                    value: "red",
+                    checked: true
+                }
                 input { r#type: "radio", name: "color", value: "blue" }
                 input { r#type: "radio", name: "color", value: "blue" }
                 button { r#type: "submit", value: "Submit", "Submit the form" }
                 button { r#type: "submit", value: "Submit", "Submit the form" }
             }
             }
@@ -547,9 +563,9 @@ fn test_select_multiple_options() -> Element {
                 assert_eq!(values, vec!["usa", "canada"]);
                 assert_eq!(values, vec!["usa", "canada"]);
                 RECEIVED_EVENTS.with_mut(|x| *x += 1);
                 RECEIVED_EVENTS.with_mut(|x| *x += 1);
             },
             },
-            option { id: "usa", value: "usa",  "USA" }
-            option { id: "canada", value: "canada",  "Canada" }
-            option { id: "mexico", value: "mexico", selected: true,  "Mexico" }
+            option { id: "usa", value: "usa", "USA" }
+            option { id: "canada", value: "canada", "Canada" }
+            option { id: "mexico", value: "mexico", selected: true, "Mexico" }
         }
         }
     }
     }
 }
 }

+ 4 - 14
packages/desktop/headless_tests/rendering.rs

@@ -1,5 +1,4 @@
 use dioxus::prelude::*;
 use dioxus::prelude::*;
-use dioxus_core::Element;
 use dioxus_desktop::DesktopContext;
 use dioxus_desktop::DesktopContext;
 
 
 #[path = "./utils.rs"]
 #[path = "./utils.rs"]
@@ -53,26 +52,17 @@ fn check_html_renders() -> Element {
     }
     }
 
 
     let dyn_value = 0;
     let dyn_value = 0;
-    let dyn_element = rsx! {
-        div {
-            dangerous_inner_html: "<p>hello world</p>",
-        }
-    };
+    let dyn_element = rsx! { div { dangerous_inner_html: "<p>hello world</p>" } };
 
 
     rsx! {
     rsx! {
-        div {
-            id: "main_div",
+        div { id: "main_div",
             div {
             div {
                 width: "100px",
                 width: "100px",
                 height: "100px",
                 height: "100px",
                 color: "rgb({dyn_value}, {dyn_value}, {dyn_value})",
                 color: "rgb({dyn_value}, {dyn_value}, {dyn_value})",
                 id: 5,
                 id: 5,
-                input {
-                    "type": "checkbox",
-                },
-                h1 {
-                    "text"
-                }
+                input { "type": "checkbox" }
+                h1 { "text" }
                 {dyn_element}
                 {dyn_element}
             }
             }
         }
         }

+ 1 - 1
packages/desktop/headless_tests/utils.rs

@@ -18,7 +18,7 @@ pub fn check_app_exits(app: fn() -> Element) {
     });
     });
 
 
     LaunchBuilder::desktop()
     LaunchBuilder::desktop()
-        .with_cfg(Config::new().with_window(WindowBuilder::new().with_visible(true)))
+        .with_cfg(Config::new().with_window(WindowBuilder::new().with_visible(false)))
         .launch(app);
         .launch(app);
 
 
     // Stop deadman's switch
     // Stop deadman's switch

+ 3 - 0
packages/dioxus-lib/Cargo.toml

@@ -19,6 +19,9 @@ dioxus-hooks = { workspace = true, optional = true }
 dioxus-rsx = { workspace = true, optional = true }
 dioxus-rsx = { workspace = true, optional = true }
 dioxus-signals = { workspace = true, optional = true }
 dioxus-signals = { workspace = true, optional = true }
 
 
+[dev-dependencies]
+dioxus = { workspace = true }
+
 [features]
 [features]
 default = ["macro", "html", "signals", "hooks"]
 default = ["macro", "html", "signals", "hooks"]
 signals = ["dioxus-signals"]
 signals = ["dioxus-signals"]

+ 3 - 3
packages/dioxus-lib/README.md

@@ -1,5 +1,5 @@
 <div>
 <div>
-  <h1>🌗🚀 Dioxus</h1>
+  <h1>🌗🚀 Dioxus (lib)</h1>
   <p>
   <p>
     <strong>A concurrent, functional, virtual DOM for Rust</strong>
     <strong>A concurrent, functional, virtual DOM for Rust</strong>
   </p>
   </p>
@@ -38,9 +38,9 @@ Remember: Dioxus is a library for declaring interactive user interfaces—it is
 
 
 All Dioxus apps are built by composing functions that return an `Element`.
 All Dioxus apps are built by composing functions that return an `Element`.
 
 
-To launch an app, we use the `launch` method and use features in ``Cargo.toml`` to specify which renderer we want to use. In the launch function, we pass the app's root `Component`.
+To launch an app, we use the `launch` method and use features in `Cargo.toml` to specify which renderer we want to use. In the launch function, we pass the app's root `Component`.
 
 
-```rust
+```rust, no_run
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {

+ 2 - 2
packages/dioxus/README.md

@@ -36,9 +36,9 @@ Remember: Dioxus is a library for declaring interactive user interfaces—it is
 
 
 All Dioxus apps are built by composing functions that return an `Element`.
 All Dioxus apps are built by composing functions that return an `Element`.
 
 
-To launch an app, we use the `launch` method and use features in ``Cargo.toml`` to specify which renderer we want to use. In the launch function, we pass the app's root `Component`.
+To launch an app, we use the `launch` method and use features in `Cargo.toml` to specify which renderer we want to use. In the launch function, we pass the app's root `Component`.
 
 
-```rust
+```rust, no_run
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
 fn main() {
 fn main() {

+ 3 - 0
packages/fullstack/Cargo.toml

@@ -66,6 +66,9 @@ tokio = { workspace = true, features = ["rt", "sync"], optional = true }
 dioxus-hot-reload = { workspace = true }
 dioxus-hot-reload = { workspace = true }
 tokio = { workspace = true, features = ["rt", "sync", "rt-multi-thread"], optional = true }
 tokio = { workspace = true, features = ["rt", "sync", "rt-multi-thread"], optional = true }
 
 
+[dev-dependencies]
+dioxus = { workspace = true, features = ["fullstack"] }
+
 [features]
 [features]
 default = ["hot-reload"]
 default = ["hot-reload"]
 hot-reload = ["serde_json"]
 hot-reload = ["serde_json"]

+ 2 - 2
packages/fullstack/README.md

@@ -32,7 +32,7 @@ Fullstack utilities for the [`Dioxus`](https://dioxuslabs.com) framework.
 
 
 Full stack Dioxus in under 30 lines of code
 Full stack Dioxus in under 30 lines of code
 
 
-```rust
+```rust, no_run
 #![allow(non_snake_case)]
 #![allow(non_snake_case)]
 use dioxus::prelude::*;
 use dioxus::prelude::*;
 
 
@@ -42,7 +42,7 @@ fn main() {
 
 
 #[component]
 #[component]
 fn App() -> Element {
 fn App() -> Element {
-    let meaning = use_signal(|| None);
+    let mut meaning = use_signal(|| None);
 
 
     rsx! {
     rsx! {
         h1 { "Meaning of life: {meaning:?}" }
         h1 { "Meaning of life: {meaning:?}" }

+ 2 - 2
packages/fullstack/src/hooks/server_cached.rs

@@ -12,9 +12,9 @@ use serde::{de::DeserializeOwned, Serialize};
 /// use dioxus_fullstack::prelude::*;
 /// use dioxus_fullstack::prelude::*;
 ///
 ///
 /// fn app() -> Element {
 /// fn app() -> Element {
-///    let state1 = server_cached(|| from_server(|| {
+///    let state1 = server_cached(|| {
 ///       1234
 ///       1234
-///    }));
+///    });
 ///
 ///
 ///    None
 ///    None
 /// }
 /// }

+ 1 - 1
packages/hooks/src/use_effect.rs

@@ -34,7 +34,7 @@ use crate::use_callback;
 /// #[component]
 /// #[component]
 /// fn Comp(count: u32) -> Element {
 /// fn Comp(count: u32) -> Element {
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
-///     use_effect(use_reactive((&count, |(count,)| println!("Manually manipulate the dom") )));
+///     use_effect(use_reactive((&count,), |(count,)| println!("Manually manipulate the dom") ));
 ///
 ///
 ///     todo!()
 ///     todo!()
 /// }
 /// }

+ 1 - 1
packages/hooks/src/use_memo.rs

@@ -32,7 +32,7 @@ use dioxus_signals::{Memo, Signal};
 /// #[component]
 /// #[component]
 /// fn Comp(count: u32) -> Element {
 /// fn Comp(count: u32) -> Element {
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
-///     let new_count = use_memo(use_reactive((&count, |(count,)| count + 1)));
+///     let new_count = use_memo(use_reactive((&count,), |(count,)| count + 1));
 ///
 ///
 ///     todo!()
 ///     todo!()
 /// }
 /// }

+ 2 - 2
packages/hooks/src/use_reactive.rs

@@ -74,7 +74,7 @@ impl_dep!(A = a1 a2, B = b1 b2, C = c1 c2, D = d1 d2, E = e1 e2, F = f1 f2, G =
 ///
 ///
 /// # Example
 /// # Example
 ///
 ///
-/// ```rust
+/// ```rust, no_run
 /// use dioxus::prelude::*;
 /// use dioxus::prelude::*;
 ///
 ///
 /// let data = 5;
 /// let data = 5;
@@ -104,7 +104,7 @@ pub fn use_reactive<O, D: Dependency>(
 ///
 ///
 /// # Example
 /// # Example
 ///
 ///
-/// ```rust
+/// ```rust, no_run
 /// use dioxus::prelude::*;
 /// use dioxus::prelude::*;
 ///
 ///
 /// let data = 5;
 /// let data = 5;

+ 1 - 5
packages/hooks/src/use_resource.rs

@@ -2,10 +2,6 @@
 
 
 use crate::{use_callback, use_signal, UseCallback};
 use crate::{use_callback, use_signal, UseCallback};
 use dioxus_core::prelude::*;
 use dioxus_core::prelude::*;
-use dioxus_core::{
-    prelude::{spawn, use_hook},
-    Task,
-};
 use dioxus_signals::*;
 use dioxus_signals::*;
 use futures_util::{future, pin_mut, FutureExt, StreamExt};
 use futures_util::{future, pin_mut, FutureExt, StreamExt};
 use std::ops::Deref;
 use std::ops::Deref;
@@ -66,7 +62,7 @@ use std::{cell::Cell, future::Future, rc::Rc};
 /// #[component]
 /// #[component]
 /// fn Comp(count: u32) -> Element {
 /// fn Comp(count: u32) -> Element {
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
 ///     // Because the memo subscribes to `count` by adding it as a dependency, the memo will rerun every time `count` changes.
-///     let new_count = use_resource(use_reactive((&count, |(count,)| async move {count + 1} )));
+///     let new_count = use_resource(use_reactive((&count,), |(count,)| async move {count + 1} ));
 ///
 ///
 ///     todo!()
 ///     todo!()
 /// }
 /// }

+ 4 - 4
packages/html/README.md

@@ -25,7 +25,7 @@ The Dioxus `rsx!` and `html!` macros can accept any compile-time correct namespa
 
 
 However, this abstraction enables you to add any namespace of elements, provided they're in scope when rsx! is called. For an example, a UI that is designed for Augmented Reality might use different primitives than HTML:
 However, this abstraction enables you to add any namespace of elements, provided they're in scope when rsx! is called. For an example, a UI that is designed for Augmented Reality might use different primitives than HTML:
 
 
-```rust
+```rust, ignore
 use ar_namespace::*;
 use ar_namespace::*;
 
 
 rsx! {
 rsx! {
@@ -46,7 +46,7 @@ This is currently a not-very-explored part of Dioxus. However, the namespacing s
 
 
 Elements for dioxus must implement the (simple) DioxusElement trait to be used in the rsx! macro.
 Elements for dioxus must implement the (simple) DioxusElement trait to be used in the rsx! macro.
 
 
-```rust
+```rust, ignore
 struct div;
 struct div;
 impl DioxusElement for div {
 impl DioxusElement for div {
     const TAG_NAME: &'static str = "div";
     const TAG_NAME: &'static str = "div";
@@ -60,7 +60,7 @@ Attributes would then be implemented as constants on these unit structs.
 
 
 The HTML namespace is defined mostly with macros. However, the expanded form would look something like this:
 The HTML namespace is defined mostly with macros. However, the expanded form would look something like this:
 
 
-```rust
+```rust, ignore
 struct base;
 struct base;
 impl DioxusElement for base {
 impl DioxusElement for base {
     const TAG_NAME: &'static str = "base";
     const TAG_NAME: &'static str = "base";
@@ -78,7 +78,7 @@ Because attributes are defined as methods on the unit struct, they guard the att
 
 
 Whenever the rsx! macro is called, it relies on a module `dioxus_elements` to be in scope. When you enable the `html` feature in dioxus, this module gets imported in the prelude. However, you can extend this with your own set of custom elements by making your own `dioxus_elements` module and re-exporting the html namespace.
 Whenever the rsx! macro is called, it relies on a module `dioxus_elements` to be in scope. When you enable the `html` feature in dioxus, this module gets imported in the prelude. However, you can extend this with your own set of custom elements by making your own `dioxus_elements` module and re-exporting the html namespace.
 
 
-```rust
+```rust, ignore
 mod dioxus_elements {
 mod dioxus_elements {
     use dioxus::prelude::dioxus_elements::*;
     use dioxus::prelude::dioxus_elements::*;
     struct my_element;
     struct my_element;

+ 3 - 1
packages/liveview/src/lib.rs

@@ -106,7 +106,9 @@ fn handle_edits_code() -> String {
 /// If you enter a relative path, the web client automatically prefixes the host address in
 /// If you enter a relative path, the web client automatically prefixes the host address in
 /// `window.location` when creating a web socket to LiveView.
 /// `window.location` when creating a web socket to LiveView.
 ///
 ///
-/// ```
+/// ```rust
+/// use dioxus_liveview::interpreter_glue;
+///
 /// // Creates websocket connection to same host as current page
 /// // Creates websocket connection to same host as current page
 /// interpreter_glue("/api/liveview");
 /// interpreter_glue("/api/liveview");
 ///
 ///

+ 3 - 0
packages/router-macro/Cargo.toml

@@ -20,6 +20,9 @@ quote = { workspace = true }
 proc-macro2 = { workspace = true }
 proc-macro2 = { workspace = true }
 slab = { workspace = true }
 slab = { workspace = true }
 
 
+[dev-dependencies]
+dioxus = { workspace = true, features = ["router"] }
+
 [features]
 [features]
 default = []
 default = []
 web = []
 web = []

+ 56 - 14
packages/router-macro/src/lib.rs

@@ -42,7 +42,9 @@ mod segment;
 /// 2. By the order they are defined in the enum
 /// 2. By the order they are defined in the enum
 ///
 ///
 /// All features:
 /// All features:
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[rustfmt::skip]
 /// #[rustfmt::skip]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
@@ -75,9 +77,17 @@ mod segment;
 ///     #[redirect("/:id/user", |id: usize| Route::Route3 { dynamic: id.to_string()})]
 ///     #[redirect("/:id/user", |id: usize| Route::Route3 { dynamic: id.to_string()})]
 ///     #[route("/:dynamic")]
 ///     #[route("/:dynamic")]
 ///     Route3 { dynamic: String },
 ///     Route3 { dynamic: String },
-///     #[child]
-///     NestedRoute(NestedRoute),
 /// }
 /// }
+/// # #[component]
+/// # fn Route1(user_id: usize, dynamic: usize, query: String) -> Element { None }
+/// # #[component]
+/// # fn Route2(user_id: usize) -> Element { None }
+/// # #[component]
+/// # fn Route3(dynamic: String) -> Element { None }
+/// # #[component]
+/// # fn UserFrame(user_id: usize) -> Element { None }
+/// # #[component]
+/// # fn IndexComponent() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// # `#[route("path", component)]`
 /// # `#[route("path", component)]`
@@ -89,7 +99,9 @@ mod segment;
 /// Routes are the most basic attribute. They allow you to define a route and the component to render when the route is matched. The component must take all dynamic parameters of the route and all parent nests.
 /// Routes are the most basic attribute. They allow you to define a route and the component to render when the route is matched. The component must take all dynamic parameters of the route and all parent nests.
 /// The next variant will be tied to the component. If you link to that variant, the component will be rendered.
 /// The next variant will be tied to the component. If you link to that variant, the component will be rendered.
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     // Define routes that renders the IndexComponent
 ///     // Define routes that renders the IndexComponent
@@ -97,6 +109,8 @@ mod segment;
 ///     #[route("/", Index)]
 ///     #[route("/", Index)]
 ///     Index {},
 ///     Index {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// # `#[redirect("path", function)]`
 /// # `#[redirect("path", function)]`
@@ -105,14 +119,18 @@ mod segment;
 /// - `path`: The path to the enum variant (relative to the parent nest)
 /// - `path`: The path to the enum variant (relative to the parent nest)
 /// - `function`: A function that takes the parameters from the path and returns a new route
 /// - `function`: A function that takes the parameters from the path and returns a new route
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     // Redirects the /:id route to the Index route
 ///     // Redirects the /:id route to the Index route
-///     #[redirect("/:id", |_: usize| Route::Index {})]
+///     #[redirect("/:id", |id: usize| Route::Index {})]
 ///     #[route("/", Index)]
 ///     #[route("/", Index)]
 ///     Index {},
 ///     Index {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// Redirects allow you to redirect a route to another route. The function must take all dynamic parameters of the route and all parent nests.
 /// Redirects allow you to redirect a route to another route. The function must take all dynamic parameters of the route and all parent nests.
@@ -124,29 +142,35 @@ mod segment;
 ///
 ///
 /// Nests effect all nests, routes and redirects defined until the next `#[end_nest]` attribute. All children of nests are relative to the nest route and must include all dynamic parameters of the nest.
 /// Nests effect all nests, routes and redirects defined until the next `#[end_nest]` attribute. All children of nests are relative to the nest route and must include all dynamic parameters of the nest.
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     // Nests all child routes in the /blog route
 ///     // Nests all child routes in the /blog route
 ///     #[nest("/blog")]
 ///     #[nest("/blog")]
 ///         // This is at /blog/:id
 ///         // This is at /blog/:id
-///         #[redirect("/:id", |_: usize| Route::Index {})]
+///         #[redirect("/:id", |id: usize| Route::Index {})]
 ///         // This is at /blog
 ///         // This is at /blog
 ///         #[route("/", Index)]
 ///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// # `#[end_nest]`
 /// # `#[end_nest]`
 ///
 ///
 /// The `#[end_nest]` attribute is used to end a nest. It takes no parameters.
 /// The `#[end_nest]` attribute is used to end a nest. It takes no parameters.
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     #[nest("/blog")]
 ///     #[nest("/blog")]
 ///         // This is at /blog/:id
 ///         // This is at /blog/:id
-///         #[redirect("/:id", |_: usize| Route::Index {})]
+///         #[redirect("/:id", |id: usize| Route::Index {})]
 ///         // This is at /blog
 ///         // This is at /blog
 ///         #[route("/", Index)]
 ///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
@@ -156,6 +180,10 @@ mod segment;
 ///     #[route("/")]
 ///     #[route("/")]
 ///     Home {},
 ///     Home {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
+/// # #[component]
+/// # fn Home() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// # `#[layout(component)]`
 /// # `#[layout(component)]`
@@ -165,26 +193,34 @@ mod segment;
 ///
 ///
 /// The layout component allows you to wrap all children of the layout in a component. The child routes are rendered in the Outlet of the layout component. The layout component must take all dynamic parameters of the nests it is nested in.
 /// The layout component allows you to wrap all children of the layout in a component. The child routes are rendered in the Outlet of the layout component. The layout component must take all dynamic parameters of the nests it is nested in.
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     #[layout(BlogFrame)]
 ///     #[layout(BlogFrame)]
-///         #[redirect("/:id", |_: usize| Route::Index {})]
+///         #[redirect("/:id", |id: usize| Route::Index {})]
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         #[route("/", Index)]
 ///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
+/// # #[component]
+/// # fn BlogFrame() -> Element { None }
 /// ```
 /// ```
 ///
 ///
 /// # `#[end_layout]`
 /// # `#[end_layout]`
 ///
 ///
 /// The `#[end_layout]` attribute is used to end a layout. It takes no parameters.
 /// The `#[end_layout]` attribute is used to end a layout. It takes no parameters.
 ///
 ///
-/// ```rust, skip
+/// ```rust
+/// use dioxus::prelude::*;
+///
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// #[derive(Clone, Debug, PartialEq, Routable)]
 /// enum Route {
 /// enum Route {
 ///     #[layout(BlogFrame)]
 ///     #[layout(BlogFrame)]
-///         #[redirect("/:id", |_: usize| Route::Index {})]
+///         #[redirect("/:id", |id: usize| Route::Index {})]
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         // Index will be rendered in the Outlet of the BlogFrame component
 ///         #[route("/", Index)]
 ///         #[route("/", Index)]
 ///         Index {},
 ///         Index {},
@@ -194,6 +230,12 @@ mod segment;
 ///     #[route("/")]
 ///     #[route("/")]
 ///     Home {},
 ///     Home {},
 /// }
 /// }
+/// # #[component]
+/// # fn Index() -> Element { None }
+/// # #[component]
+/// # fn BlogFrame() -> Element { None }
+/// # #[component]
+/// # fn Home() -> Element { None }
 /// ```
 /// ```
 #[proc_macro_derive(
 #[proc_macro_derive(
     Routable,
     Routable,

+ 13 - 3
packages/router/src/components/history_buttons.rs

@@ -73,7 +73,12 @@ pub fn GoBackButton(props: HistoryButtonProps) -> Element {
     let disabled = !router.can_go_back();
     let disabled = !router.can_go_back();
 
 
     rsx! {
     rsx! {
-        button { disabled: "{disabled}", prevent_default: "onclick", onclick: move |_| router.go_back(), {children} }
+        button {
+            disabled: "{disabled}",
+            prevent_default: "onclick",
+            onclick: move |_| router.go_back(),
+            {children}
+        }
     }
     }
 }
 }
 
 
@@ -114,7 +119,7 @@ pub fn GoBackButton(props: HistoryButtonProps) -> Element {
 /// }
 /// }
 /// #
 /// #
 /// # let mut vdom = VirtualDom::new(App);
 /// # let mut vdom = VirtualDom::new(App);
-/// # let _ = vdom.rebuild();
+/// # vdom.rebuild_in_place();
 /// # assert_eq!(
 /// # assert_eq!(
 /// #     dioxus_ssr::render(&vdom),
 /// #     dioxus_ssr::render(&vdom),
 /// #     r#"<button disabled="true" dioxus-prevent-default="onclick">go forward</button>"#
 /// #     r#"<button disabled="true" dioxus-prevent-default="onclick">go forward</button>"#
@@ -139,6 +144,11 @@ pub fn GoForwardButton(props: HistoryButtonProps) -> Element {
     let disabled = !router.can_go_forward();
     let disabled = !router.can_go_forward();
 
 
     rsx! {
     rsx! {
-        button { disabled: "{disabled}", prevent_default: "onclick", onclick: move |_| router.go_forward(), {children} }
+        button {
+            disabled: "{disabled}",
+            prevent_default: "onclick",
+            onclick: move |_| router.go_forward(),
+            {children}
+        }
     }
     }
 }
 }

+ 10 - 12
packages/router/src/components/link.rs

@@ -178,26 +178,24 @@ impl Debug for LinkProps {
 /// #[component]
 /// #[component]
 /// fn Index() -> Element {
 /// fn Index() -> Element {
 ///     rsx! {
 ///     rsx! {
-///         rsx! {
-///             Link {
-///                 active_class: "active",
-///                 class: "link_class",
-///                 id: "link_id",
-///                 new_tab: true,
-///                 rel: "link_rel",
-///                 to: Route::Index {},
+///         Link {
+///             active_class: "active",
+///             class: "link_class",
+///             id: "link_id",
+///             new_tab: true,
+///             rel: "link_rel",
+///             to: Route::Index {},
 ///
 ///
-///                 "A fully configured link"
-///             }
+///             "A fully configured link"
 ///         }
 ///         }
 ///     }
 ///     }
 /// }
 /// }
 /// #
 /// #
 /// # let mut vdom = VirtualDom::new(App);
 /// # let mut vdom = VirtualDom::new(App);
-/// # let _ = vdom.rebuild();
+/// # vdom.rebuild_in_place();
 /// # assert_eq!(
 /// # assert_eq!(
 /// #     dioxus_ssr::render(&vdom),
 /// #     dioxus_ssr::render(&vdom),
-/// #     r#"<a href="/" dioxus-prevent-default="" class="link_class active" id="link_id" rel="link_rel" target="_blank">A fully configured link</a>"#
+/// #     r#"<a href="/" dioxus-prevent-default="" class="link_class active" rel="link_rel" target="_blank" id="link_id">A fully configured link</a>"#
 /// # );
 /// # );
 /// ```
 /// ```
 #[allow(non_snake_case)]
 #[allow(non_snake_case)]

+ 1 - 1
packages/router/src/components/outlet.rs

@@ -65,7 +65,7 @@ use dioxus_lib::prelude::*;
 /// # }
 /// # }
 /// #
 /// #
 /// # let mut vdom = VirtualDom::new(App);
 /// # let mut vdom = VirtualDom::new(App);
-/// # let _ = vdom.rebuild();
+/// # vdom.rebuild_in_place();
 /// # assert_eq!(dioxus_ssr::render(&vdom), "<h1>App</h1><p>Child</p>");
 /// # assert_eq!(dioxus_ssr::render(&vdom), "<h1>App</h1><p>Child</p>");
 /// ```
 /// ```
 pub fn Outlet<R: Routable + Clone>() -> Element {
 pub fn Outlet<R: Routable + Clone>() -> Element {

+ 1 - 1
packages/router/src/hooks/use_navigator.rs

@@ -46,7 +46,7 @@ use crate::prelude::{Navigator, RouterContext};
 /// }
 /// }
 ///
 ///
 /// # let mut vdom = VirtualDom::new(App);
 /// # let mut vdom = VirtualDom::new(App);
-/// # let _ = vdom.rebuild();
+/// # vdom.rebuild_in_place();
 /// ```
 /// ```
 #[must_use]
 #[must_use]
 pub fn use_navigator() -> Navigator {
 pub fn use_navigator() -> Navigator {

+ 1 - 1
packages/router/src/hooks/use_route.rs

@@ -37,7 +37,7 @@ use crate::utils::use_router_internal::use_router_internal;
 /// }
 /// }
 /// #
 /// #
 /// # let mut vdom = VirtualDom::new(App);
 /// # let mut vdom = VirtualDom::new(App);
-/// # let _ = vdom.rebuild();
+/// # vdom.rebuild_in_place();
 /// # assert_eq!(dioxus_ssr::render(&vdom), "<h1>App</h1><h2>Current Path</h2><p>/</p>")
 /// # assert_eq!(dioxus_ssr::render(&vdom), "<h1>App</h1><h2>Current Path</h2><p>/</p>")
 /// ```
 /// ```
 #[must_use]
 #[must_use]

+ 3 - 3
packages/ssr/README.md

@@ -21,7 +21,7 @@ Dioxus SSR provides utilities to render Dioxus components to valid HTML. Once re
 let app: Component = |cx| rsx!(div {"hello world!"});
 let app: Component = |cx| rsx!(div {"hello world!"});
 
 
 let mut vdom = VirtualDom::new(app);
 let mut vdom = VirtualDom::new(app);
-let _ = vdom.rebuild();
+vdom.rebuild_in_place();
 
 
 let text = dioxus_ssr::render(&vdom);
 let text = dioxus_ssr::render(&vdom);
 assert_eq!(text, "<div>hello world!</div>")
 assert_eq!(text, "<div>hello world!</div>")
@@ -45,7 +45,7 @@ let content = dioxus_ssr::render_element(rsx!{
 
 
 ```rust, ignore
 ```rust, ignore
 let mut vdom = VirtualDom::new(app);
 let mut vdom = VirtualDom::new(app);
-let _ = vdom.rebuild();
+vdom.rebuild_in_place();
 
 
 let content = dioxus_ssr::render(&vdom);
 let content = dioxus_ssr::render(&vdom);
 ```
 ```
@@ -63,7 +63,7 @@ To enable pre-rendering, simply set the pre-rendering flag to true.
 ```rust, ignore
 ```rust, ignore
 let mut vdom = VirtualDom::new(App);
 let mut vdom = VirtualDom::new(App);
 
 
-let _ = vdom.rebuild();
+vdom.rebuild_in_place();
 
 
 let mut renderer = dioxus_ssr::Renderer::new();
 let mut renderer = dioxus_ssr::Renderer::new();
 renderer.pre_render = true;
 renderer.pre_render = true;