diff --git a/packages/dioxus-tui/tests/events.rs b/packages/dioxus-tui/tests/events.rs index ea227f99b..0f4348a19 100644 --- a/packages/dioxus-tui/tests/events.rs +++ b/packages/dioxus-tui/tests/events.rs @@ -33,14 +33,15 @@ fn key_down() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let mut render_count_handle = render_count.clone(); + let tui_ctx: TuiContext = consume_context(); + + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } // focus the element @@ -74,14 +75,14 @@ fn mouse_down() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(2).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -110,14 +111,14 @@ fn mouse_up() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -149,14 +150,14 @@ fn mouse_enter() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let mut render_count_handle = render_count.clone(); + let tui_ctx: TuiContext = consume_context(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -188,14 +189,14 @@ fn mouse_exit() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -227,14 +228,14 @@ fn mouse_move() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -266,14 +267,14 @@ fn wheel() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -306,14 +307,14 @@ fn click() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { @@ -345,14 +346,14 @@ fn context_menu() { dioxus_tui::launch_cfg(app, dioxus_tui::Config::new().with_headless()); fn app() -> Element { - let render_count = use_signal(|| 0); - let tui_ctx: TuiContext = cx.consume_context().unwrap(); - let render_count_handle = render_count.clone(); - cx.spawn(async move { + let mut render_count = use_signal(|| 0); + let tui_ctx: TuiContext = consume_context(); + let mut render_count_handle = render_count.clone(); + spawn(async move { PollN::new(3).await; - render_count_handle.modify(|x| *x + 1); + render_count_handle.with_mut(|x| *x + 1); }); - if *render_count.get() > 2 { + if render_count() > 2 { panic!("Event was not received"); } tui_ctx.inject_event(Event::Mouse(MouseEvent { diff --git a/packages/native-core/tests/called_minimally_on_build.rs b/packages/native-core/_tests/called_minimally_on_build.rs similarity index 100% rename from packages/native-core/tests/called_minimally_on_build.rs rename to packages/native-core/_tests/called_minimally_on_build.rs diff --git a/packages/native-core/tests/custom_element.rs b/packages/native-core/_tests/custom_element.rs similarity index 100% rename from packages/native-core/tests/custom_element.rs rename to packages/native-core/_tests/custom_element.rs diff --git a/packages/native-core/tests/fuzzing.rs b/packages/native-core/_tests/fuzzing.rs similarity index 99% rename from packages/native-core/tests/fuzzing.rs rename to packages/native-core/_tests/fuzzing.rs index f039d16be..cd8e97be8 100644 --- a/packages/native-core/tests/fuzzing.rs +++ b/packages/native-core/_tests/fuzzing.rs @@ -175,7 +175,7 @@ fn create_random_template(name: &'static str) -> (Template, Vec ) } -fn create_random_dynamic_node(, depth: usize) -> DynamicNode { +fn create_random_dynamic_node(depth: usize) -> DynamicNode { let range = if depth > 3 { 1 } else { 3 }; match rand::random::() % range { 0 => DynamicNode::Placeholder(Default::default()), diff --git a/packages/native-core/tests/miri_native.rs b/packages/native-core/_tests/miri_native.rs similarity index 100% rename from packages/native-core/tests/miri_native.rs rename to packages/native-core/_tests/miri_native.rs diff --git a/packages/native-core/tests/passes.rs b/packages/native-core/_tests/passes.rs similarity index 100% rename from packages/native-core/tests/passes.rs rename to packages/native-core/_tests/passes.rs diff --git a/packages/native-core/src/utils/persistant_iterator.rs b/packages/native-core/src/utils/persistant_iterator.rs index 5fe456c44..7cf7bf454 100644 --- a/packages/native-core/src/utils/persistant_iterator.rs +++ b/packages/native-core/src/utils/persistant_iterator.rs @@ -216,13 +216,12 @@ fn traverse() { } let mut vdom = VirtualDom::new(Base); - let mutations = vdom.rebuild(); let mut rdom: RealDom = RealDom::new([]); let mut iter = PersistantElementIter::create(&mut rdom); let mut dioxus_state = DioxusState::create(&mut rdom); - dioxus_state.apply_mutations(&mut rdom, mutations); + vdom.rebuild(&mut dioxus_state.create_mutation_writer(&mut rdom)); let div_tag = "div".to_string(); assert!(matches!( @@ -317,14 +316,13 @@ fn persist_removes() { let mut rdom: RealDom = RealDom::new([]); - let build = vdom.rebuild(); - println!("{build:#?}"); // this will end on the node that is removed let mut iter1 = PersistantElementIter::create(&mut rdom); // this will end on the after node that is removed let mut iter2 = PersistantElementIter::create(&mut rdom); let mut dioxus_state = DioxusState::create(&mut rdom); - dioxus_state.apply_mutations(&mut rdom, build); + + vdom.rebuild(&mut dioxus_state.create_mutation_writer(&mut rdom)); // root iter1.next(&rdom).id(); @@ -350,9 +348,7 @@ fn persist_removes() { iter2.next(&rdom).id(); vdom.mark_dirty(ScopeId::ROOT); - let update = vdom.render_immediate(); - println!("{update:#?}"); - dioxus_state.apply_mutations(&mut rdom, update); + vdom.render_immediate(&mut dioxus_state.create_mutation_writer(&mut rdom)); let root_tag = "Root".to_string(); let idx = iter1.next(&rdom).id(); @@ -394,8 +390,7 @@ fn persist_instertions_before() { let mut rdom: RealDom = RealDom::new([]); let mut dioxus_state = DioxusState::create(&mut rdom); - let build = vdom.rebuild(); - dioxus_state.apply_mutations(&mut rdom, build); + vdom.rebuild(&mut dioxus_state.create_mutation_writer(&mut rdom)); let mut iter = PersistantElementIter::create(&mut rdom); // div @@ -410,8 +405,7 @@ fn persist_instertions_before() { iter.next(&rdom).id(); vdom.mark_dirty(ScopeId::ROOT); - let update = vdom.render_immediate(); - dioxus_state.apply_mutations(&mut rdom, update); + vdom.render_immediate(&mut dioxus_state.create_mutation_writer(&mut rdom)); let p_tag = "div".to_string(); let idx = iter.next(&rdom).id(); @@ -448,8 +442,8 @@ fn persist_instertions_after() { let mut iter = PersistantElementIter::create(&mut rdom); let mut dioxus_state = DioxusState::create(&mut rdom); - let build = vdom.rebuild(); - dioxus_state.apply_mutations(&mut rdom, build); + let mut writer = dioxus_state.create_mutation_writer(&mut rdom); + vdom.rebuild(&mut writer); // div iter.next(&rdom).id(); @@ -462,8 +456,8 @@ fn persist_instertions_after() { // "world" iter.next(&rdom).id(); - let update = vdom.rebuild(); - dioxus_state.apply_mutations(&mut rdom, update); + let mut writer = dioxus_state.create_mutation_writer(&mut rdom); + vdom.rebuild(&mut writer); let p_tag = "p".to_string(); let idx = iter.next(&rdom).id(); diff --git a/packages/router/src/components/link.rs b/packages/router/src/components/link.rs index 089784e43..dc21b3a8a 100644 --- a/packages/router/src/components/link.rs +++ b/packages/router/src/components/link.rs @@ -83,15 +83,19 @@ impl From<&Url> for IntoRoutable { pub struct LinkProps { /// A class to apply to the generate HTML anchor tag if the `target` route is active. pub active_class: Option, + /// The children to render within the generated HTML anchor tag. pub children: Element, + /// When [`true`], the `target` route will be opened in a new tab. /// /// This does not change whether the [`Link`] is active or not. #[props(default)] pub new_tab: bool, + /// The onclick event handler. pub onclick: Option>, + #[props(default)] /// Whether the default behavior should be executed if an `onclick` handler is provided. /// @@ -100,13 +104,16 @@ pub struct LinkProps { /// will be executed after the links regular functionality. /// 3. If `onclick_only` is [`true`], only the provided `onclick` handler will be executed. pub onclick_only: bool, + /// The rel attribute for the generated HTML anchor tag. /// /// For external `a`s, this defaults to `noopener noreferrer`. pub rel: Option, + /// The navigation target. Roughly equivalent to the href attribute of an HTML anchor tag. #[props(into)] pub to: IntoRoutable, + #[props(extends = GlobalAttributes)] attributes: Vec, } diff --git a/packages/router/tests/via_ssr/link.rs b/packages/router/tests/via_ssr/link.rs index 699a245eb..de551dca0 100644 --- a/packages/router/tests/via_ssr/link.rs +++ b/packages/router/tests/via_ssr/link.rs @@ -12,7 +12,7 @@ where phantom: std::marker::PhantomData, }, ); - let _ = vdom.rebuild(); + vdom.rebuild_in_place(); return dioxus_ssr::render(&vdom); #[derive(Props)] @@ -20,14 +20,21 @@ where phantom: std::marker::PhantomData, } + impl Clone for AppProps { + fn clone(&self) -> Self { + Self { + phantom: std::marker::PhantomData, + } + } + } + impl PartialEq for AppProps { fn eq(&self, _other: &Self) -> bool { false } } - #[component] - fn App(cx: Scope>) -> Element + fn App(props: AppProps) -> Element where ::Err: std::fmt::Display, { @@ -51,7 +58,7 @@ fn href_internal() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -89,7 +96,7 @@ fn href_external() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -127,7 +134,7 @@ fn with_class() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -168,7 +175,7 @@ fn with_active_class_active() { rsx! { Link { to: Route::Root {}, - active_class: "active_class", + active_class: "active_class".to_string(), class: "test_class", "Link" } @@ -199,7 +206,7 @@ fn with_active_class_inactive() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -208,7 +215,7 @@ fn with_active_class_inactive() { rsx! { Link { to: Route::Test {}, - active_class: "active_class", + active_class: "active_class".to_string(), class: "test_class", "Link" } @@ -239,7 +246,7 @@ fn with_id() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -278,7 +285,7 @@ fn with_new_tab() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -349,7 +356,7 @@ fn with_rel() { } #[component] - fn Test(_cx: Scope) -> Element { + fn Test() -> Element { todo!() } @@ -358,7 +365,7 @@ fn with_rel() { rsx! { Link { to: Route::Test {}, - rel: "test_rel", + rel: "test_rel".to_string(), "Link" } } diff --git a/packages/router/tests/via_ssr/outlet.rs b/packages/router/tests/via_ssr/outlet.rs index b73a9f8e6..4dd07130e 100644 --- a/packages/router/tests/via_ssr/outlet.rs +++ b/packages/router/tests/via_ssr/outlet.rs @@ -5,7 +5,7 @@ use dioxus_router::prelude::*; fn prepare(path: impl Into) -> VirtualDom { let mut vdom = VirtualDom::new_with_props(App, AppProps { path: path.into() }); - let _ = vdom.rebuild(); + vdom.rebuild_in_place(); return vdom; #[derive(Routable, Clone)] @@ -29,18 +29,13 @@ fn prepare(path: impl Into) -> VirtualDom { ParameterFixed { id: u8 }, } - #[derive(Debug, Props, PartialEq)] - struct AppProps { - path: String, - } - #[component] - fn App(cx: Scope) -> Element { + fn App(path: String) -> Element { rsx! { h1 { "App" } Router:: { config: { - let path = cx.props.path.parse().unwrap(); + let path = path.parse().unwrap(); move || RouterConfig::default().history(MemoryHistory::with_initial_path(path)) } } @@ -49,9 +44,7 @@ fn prepare(path: impl Into) -> VirtualDom { #[component] fn RootIndex() -> Element { - rsx! { - h2 { "Root Index" } - } + rsx! { h2 { "Root Index" } } } #[component] @@ -64,16 +57,12 @@ fn prepare(path: impl Into) -> VirtualDom { #[component] fn FixedIndex() -> Element { - rsx! { - h3 { "Fixed - Index" } - } + rsx! { h3 { "Fixed - Index" } } } #[component] fn FixedFixed() -> Element { - rsx! { - h3 { "Fixed - Fixed"} - } + rsx! { h3 { "Fixed - Fixed"} } } #[component] @@ -86,16 +75,12 @@ fn prepare(path: impl Into) -> VirtualDom { #[component] fn ParameterIndex(id: u8) -> Element { - rsx! { - h3 { "Parameter - Index" } - } + rsx! { h3 { "Parameter - Index" } } } #[component] fn ParameterFixed(id: u8) -> Element { - rsx! { - h3 { "Parameter - Fixed" } - } + rsx! { h3 { "Parameter - Fixed" } } } } diff --git a/packages/rsx/src/lib.rs b/packages/rsx/src/lib.rs index 484f38151..94d61a08e 100644 --- a/packages/rsx/src/lib.rs +++ b/packages/rsx/src/lib.rs @@ -662,9 +662,8 @@ fn create_template() { #[cfg(feature = "hot_reload")] #[test] fn diff_template() { - use dioxus_core::Scope; #[allow(unused, non_snake_case)] - fn Comp(_: Scope) -> dioxus_core::Element { + fn Comp() -> dioxus_core::Element { None } diff --git a/packages/signals/tests/create.rs b/packages/signals/tests/create.rs deleted file mode 100644 index db5cce57d..000000000 --- a/packages/signals/tests/create.rs +++ /dev/null @@ -1,84 +0,0 @@ -#![allow(unused, non_upper_case_globals, non_snake_case)] - -use dioxus::prelude::*; -use dioxus_core::ElementId; -use dioxus_signals::*; - -#[test] -fn create_signals_global() { - let mut dom = VirtualDom::new(|cx| { - rsx! { - for _ in 0..10 { - Child {} - } - } - }); - - fn Child() -> Element { - let signal = create_without_cx(); - - rsx! { - "{signal}" - } - } - - let _edits = dom.rebuild().santize(); - - fn create_without_cx() -> Signal { - Signal::new("hello world".to_string()) - } -} - -#[test] -fn deref_signal() { - let mut dom = VirtualDom::new(|cx| { - rsx! { - for _ in 0..10 { - Child {} - } - } - }); - - fn Child() -> Element { - let signal = Signal::new("hello world".to_string()); - - // You can call signals like functions to get a Ref of their value. - assert_eq!(&*signal(), "hello world"); - - rsx! { - "hello world" - } - } - - let _edits = dom.rebuild().santize(); -} - -#[test] -fn drop_signals() { - let mut dom = VirtualDom::new(|cx| { - let generation = generation(); - - let count = if generation % 2 == 0 { 10 } else { 0 }; - rsx! { - for _ in 0..count { - Child {} - } - } - }); - - fn Child() -> Element { - let signal = create_without_cx(); - - rsx! { - "{signal}" - } - } - - let _ = dom.rebuild().santize(); - dom.mark_dirty(ScopeId::ROOT); - dom.render_immediate(); - - fn create_without_cx() -> Signal { - Signal::new("hello world".to_string()) - } -} diff --git a/packages/signals/tests/effect.rs b/packages/signals/tests/effect.rs deleted file mode 100644 index f30ee027a..000000000 --- a/packages/signals/tests/effect.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![allow(unused, non_upper_case_globals, non_snake_case)] -use std::collections::HashMap; -use std::rc::Rc; - -use dioxus::prelude::*; -use dioxus_core::ElementId; -use dioxus_signals::*; - -#[tokio::test] -async fn effects_rerun() { - simple_logger::SimpleLogger::new().init().unwrap(); - - #[derive(Default)] - struct RunCounter { - component: usize, - effect: usize, - } - - let counter = Rc::new(RefCell::new(RunCounter::default())); - let mut dom = VirtualDom::new_with_props( - |cx| { - let counter = cx.props; - counter.borrow_mut().component += 1; - - let mut signal = use_signal(|| 0); - cx.use_hook(move || { - to_owned![counter]; - Effect::new(move || { - counter.borrow_mut().effect += 1; - println!("Signal: {:?}", signal); - }) - }); - signal += 1; - - rsx! { div {} } - }, - counter.clone(), - ); - - let _ = dom.rebuild().santize(); - dom.render_with_deadline(tokio::time::sleep(std::time::Duration::from_millis(100))) - .await; - - let current_counter = counter.borrow(); - assert_eq!(current_counter.component, 1); - assert_eq!(current_counter.effect, 2); -} diff --git a/packages/signals/tests/map.rs b/packages/signals/tests/map.rs deleted file mode 100644 index bea13009a..000000000 --- a/packages/signals/tests/map.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![allow(unused, non_upper_case_globals, non_snake_case)] - -use dioxus::prelude::*; -use dioxus_core::ElementId; -use dioxus_signals::*; - -#[test] -fn create_signals_global() { - let mut dom = VirtualDom::new(|cx| { - render! { - for _ in 0..10 { - Child {} - } - } - }); - - fn Child(cx: Scope) -> Element { - let signal = create_without_cx(); - let mapped = MappedSignal::new(signal, |v| v.as_bytes()); - - render! { "{signal:?}", "{mapped:?}" } - } - - let _edits = dom.rebuild().santize(); - - fn create_without_cx() -> Signal { - Signal::new("hello world".to_string()) - } -} diff --git a/packages/signals/tests/selector.rs b/packages/signals/tests/selector.rs deleted file mode 100644 index 7c9441f29..000000000 --- a/packages/signals/tests/selector.rs +++ /dev/null @@ -1,146 +0,0 @@ -#![allow(unused, non_upper_case_globals, non_snake_case)] -use std::collections::HashMap; -use std::rc::Rc; - -use dioxus::html::p; -use dioxus::prelude::*; -use dioxus_core::ElementId; -use dioxus_signals::*; - -#[test] -fn memos_rerun() { - let _ = simple_logger::SimpleLogger::new().init(); - - #[derive(Default)] - struct RunCounter { - component: usize, - effect: usize, - } - - let counter = Rc::new(RefCell::new(RunCounter::default())); - let mut dom = VirtualDom::new_with_props( - |cx| { - let counter = cx.props; - counter.borrow_mut().component += 1; - - let mut signal = use_signal(|| 0); - let memo = cx.use_hook(move || { - to_owned![counter]; - selector(move || { - counter.borrow_mut().effect += 1; - println!("Signal: {:?}", signal); - signal.cloned() - }) - }); - let generation = use_signal(cx, || cx.generation()); - generation.set(cx.generation()); - dioxus_signals::use_effect(cx, move || { - if generation == 1 { - assert_eq!(memo.value(), 0); - } - if generation == 3 { - assert_eq!(memo.value(), 1); - } - }); - signal += 1; - - rsx! { div {} } - }, - counter.clone(), - ); - - let _ = dom.rebuild().santize(); - let _ = dom.render_immediate(); - - let current_counter = counter.borrow(); - assert_eq!(current_counter.component, 1); - assert_eq!(current_counter.effect, 2); -} - -#[tokio::test] -async fn memos_prevents_component_rerun() { - let _ = simple_logger::SimpleLogger::new().init(); - - #[derive(Default)] - struct RunCounter { - component: usize, - effect: usize, - } - - let counter = Rc::new(RefCell::new(RunCounter::default())); - let mut dom = VirtualDom::new_with_props( - |cx| { - let mut signal = use_signal(|| 0); - - if generation() == 1 { - *signal.write() = 0; - } - if generation() == 2 { - println!("Writing to signal"); - *signal.write() = 1; - } - - rsx! { Child { signal: signal, counter: cx.props.clone() } } - }, - counter.clone(), - ); - - #[derive(Default, Props)] - struct ChildProps { - signal: Signal, - counter: Rc>, - } - - impl PartialEq for ChildProps { - fn eq(&self, other: &Self) -> bool { - self.signal == other.signal - } - } - - fn Child(cx: Scope) -> Element { - let counter = &cx.props.counter; - let signal = cx.props.signal; - counter.borrow_mut().component += 1; - - let memo = cx.use_hook(move || { - to_owned![counter]; - selector(move || { - counter.borrow_mut().effect += 1; - println!("Signal: {:?}", signal); - signal.value() - }) - }); - match generation() { - 0 => { - assert_eq!(memo.value(), 0); - } - 1 => { - assert_eq!(memo.value(), 1); - } - _ => panic!("Unexpected generation"), - } - - rsx! { div {} } - } - - let _ = dom.rebuild().santize(); - dom.mark_dirty(ScopeId::ROOT); - dom.render_immediate(); - dom.render_immediate(); - - { - let current_counter = counter.borrow(); - assert_eq!(current_counter.component, 1); - assert_eq!(current_counter.effect, 2); - } - - dom.mark_dirty(ScopeId::ROOT); - dom.render_immediate(); - dom.render_immediate(); - - { - let current_counter = counter.borrow(); - assert_eq!(current_counter.component, 2); - assert_eq!(current_counter.effect, 3); - } -} diff --git a/packages/signals/tests/subscribe.rs b/packages/signals/tests/subscribe.rs deleted file mode 100644 index 03d895b3f..000000000 --- a/packages/signals/tests/subscribe.rs +++ /dev/null @@ -1,92 +0,0 @@ -#![allow(unused, non_upper_case_globals, non_snake_case)] -use std::collections::HashMap; -use std::rc::Rc; - -use dioxus::prelude::*; -use dioxus_core::ElementId; -use dioxus_signals::*; - -#[test] -fn reading_subscribes() { - simple_logger::SimpleLogger::new().init().unwrap(); - - #[derive(Default)] - struct RunCounter { - parent: usize, - children: HashMap, - } - - let counter = Rc::new(RefCell::new(RunCounter::default())); - let mut dom = VirtualDom::new_with_props( - |cx| { - let mut signal = use_signal(|| 0); - - println!("Parent: {:?}", cx.scope_id()); - if generation() == 1 { - signal += 1; - } - - cx.props.borrow_mut().parent += 1; - - rsx! { - for id in 0..10 { - Child { - signal: signal, - counter: cx.props.clone() - } - } - } - }, - counter.clone(), - ); - - #[derive(Props, Clone)] - struct ChildProps { - signal: Signal, - counter: Rc>, - } - - impl PartialEq for ChildProps { - fn eq(&self, other: &Self) -> bool { - self.signal == other.signal - } - } - - fn Child(cx: Scope) -> Element { - println!("Child: {:?}", cx.scope_id()); - *cx.props - .counter - .borrow_mut() - .children - .entry(cx.scope_id()) - .or_default() += 1; - - rsx! { - "{cx.props.signal}" - } - } - - let _ = dom.rebuild().santize(); - - { - let current_counter = counter.borrow(); - assert_eq!(current_counter.parent, 1); - - for (scope_id, rerun_count) in current_counter.children.iter() { - assert_eq!(rerun_count, &1); - } - } - - dom.mark_dirty(ScopeId::ROOT); - dom.render_immediate(); - dom.render_immediate(); - - { - let current_counter = counter.borrow(); - assert_eq!(current_counter.parent, 2); - - for (scope_id, rerun_count) in current_counter.children.iter() { - assert_eq!(rerun_count, &2); - } - } -} diff --git a/packages/web/src/launch.rs b/packages/web/src/launch.rs index 760bcf87b..c30bc9eb3 100644 --- a/packages/web/src/launch.rs +++ b/packages/web/src/launch.rs @@ -27,3 +27,9 @@ pub fn launch_virtual_dom(vdom: VirtualDom, platform_config: Config) { crate::run(vdom, platform_config).await; }); } + +/// +pub fn launch_cfg(root: fn() -> Element, platform_config: Config) { + let mut vdom = VirtualDom::new(root); + launch_virtual_dom(vdom, platform_config); +} diff --git a/packages/web/tests/hydrate.rs b/packages/web/tests/hydrate.rs index fff3ed39c..eb9e2d26e 100644 --- a/packages/web/tests/hydrate.rs +++ b/packages/web/tests/hydrate.rs @@ -52,5 +52,5 @@ fn rehydrates() { .unwrap() .set_inner_html(&format!("
{out}
")); - dioxus_web::launch_cfg(app, Config::new().hydrate(true)); + dioxus_web::launch::launch_cfg(app, Config::new().hydrate(true)); }