diff --git a/packages/core/src/component.rs b/packages/core/src/component.rs index 36cf908e8..d19ec6581 100644 --- a/packages/core/src/component.rs +++ b/packages/core/src/component.rs @@ -29,7 +29,7 @@ use crate::innerlude::{Context, DomTree, LazyNodes, FC}; /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it. /// #[allow(non_upper_case_globals, non_snake_case)] -pub fn Fragment<'a>(cx: Context<'a, ()>) -> DomTree<'a> { +pub fn Fragment<'a>(cx: Context<'a>, props: &'a ()) -> DomTree<'a> { cx.render(LazyNodes::new(|f| f.fragment_from_iter(cx.children()))) } diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index 7915601ca..65b3d9710 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -27,16 +27,15 @@ use std::{any::TypeId, ops::Deref, rc::Rc}; /// } /// } /// ``` -pub struct Context<'src, T> { - pub props: &'src T, +pub struct Context<'src> { pub scope: &'src Scope, } -impl<'src, T> Copy for Context<'src, T> {} -impl<'src, T> Clone for Context<'src, T> { +impl<'src> Copy for Context<'src> {} +impl<'src> Clone for Context<'src> { fn clone(&self) -> Self { Self { - props: self.props, + // props: self.props, scope: self.scope, } } @@ -44,14 +43,14 @@ impl<'src, T> Clone for Context<'src, T> { // We currently deref to props, but it might make more sense to deref to Scope? // This allows for code that takes cx.xyz instead of cx.props.xyz -impl<'a, T> Deref for Context<'a, T> { - type Target = &'a T; +impl<'a> Deref for Context<'a> { + type Target = &'a Scope; fn deref(&self) -> &Self::Target { - &self.props + &self.scope } } -impl<'src, P> Context<'src, P> { +impl<'src> Context<'src> { /// Access the children elements passed into the component /// /// This enables patterns where a component is passed children from its parent. diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs index 8121e958a..fcbf640d1 100644 --- a/packages/core/src/hooks.rs +++ b/packages/core/src/hooks.rs @@ -24,8 +24,8 @@ use std::{ /// /// /// -pub fn use_task<'src, Out, Fut, Init, P>( - cx: Context<'src, P>, +pub fn use_task<'src, Out, Fut, Init>( + cx: Context<'src>, task_initializer: Init, ) -> (&'src TaskHandle, &'src Option) where @@ -83,8 +83,8 @@ where /// # Example /// /// -pub fn use_suspense<'src, Out, Fut, Cb, P>( - cx: Context<'src, P>, +pub fn use_suspense<'src, Out, Fut, Cb>( + cx: Context<'src>, task_initializer: impl FnOnce() -> Fut, user_callback: Cb, ) -> DomTree<'src> @@ -123,10 +123,7 @@ where Some(value) => { let out = value.downcast_ref::().unwrap(); let sus = SuspendedContext { - inner: Context { - props: &(), - scope: cx.scope, - }, + inner: Context { scope: cx.scope }, }; user_callback(sus, out) } @@ -171,7 +168,7 @@ pub(crate) struct SuspenseHook { } pub struct SuspendedContext<'a> { - pub(crate) inner: Context<'a, ()>, + pub(crate) inner: Context<'a>, } impl<'src> SuspendedContext<'src> { @@ -196,7 +193,7 @@ impl<'a, T> Deref for NodeRef<'a, T> { } } -pub fn use_node_ref(cx: Context

) -> NodeRef { +pub fn use_node_ref(cx: Context) -> NodeRef { cx.use_hook( |f| {}, |f| { diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 6c6923204..33aa21ede 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -54,7 +54,7 @@ pub(crate) mod innerlude { pub use crate::virtual_dom::*; pub type DomTree<'a> = Option>; - pub type FC

= fn(Context

) -> DomTree; + pub type FC

= for<'a> fn(Context<'a>, &'a P) -> DomTree<'a>; pub use dioxus_core_macro::{format_args_f, html, rsx}; } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index daf264fc6..555a9c285 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -511,7 +511,7 @@ impl<'a> NodeFactory<'a> { let caller: &'a mut dyn for<'b> Fn(&'b Scope) -> DomTree<'b> = bump.alloc(move |scope: &Scope| -> DomTree { let props: &'_ P = unsafe { &*(raw_props as *const P) }; - let res = component(Context { props, scope }); + let res = component(Context { scope }, props); unsafe { std::mem::transmute(res) } }); diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index 357cf2e2e..ff5535607 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -275,10 +275,7 @@ impl Scope { let sus: &'a VSuspended<'a> = unsafe { std::mem::transmute(sus) }; let cx: SuspendedContext<'a> = SuspendedContext { - inner: Context { - props: &(), - scope: self, - }, + inner: Context { scope: self }, }; let mut cb = sus.callback.borrow_mut().take().unwrap(); diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index e331fe26d..9f83138da 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -130,7 +130,7 @@ impl VirtualDom { // Safety: this callback is only valid for the lifetime of the root props let root_caller: Box DomTree> = Box::new(move |scope: &Scope| unsafe { let props: &'_ P = &*(props_ptr as *const P); - std::mem::transmute(root(Context { props, scope })) + std::mem::transmute(root(Context { scope }, props)) }); let scheduler = Scheduler::new(); @@ -203,7 +203,7 @@ impl VirtualDom { let root_caller: Box DomTree> = Box::new(move |scope: &Scope| unsafe { let props: &'_ P = &*(props_ptr as *const P); - std::mem::transmute(root(Context { props, scope })) + std::mem::transmute(root(Context { scope }, props)) }); root_scope.update_scope_dependencies(&root_caller, ScopeChildren(&[])); diff --git a/packages/core/tests/borrowedstate.rs b/packages/core/tests/borrowedstate.rs new file mode 100644 index 000000000..1c40ce7ca --- /dev/null +++ b/packages/core/tests/borrowedstate.rs @@ -0,0 +1,45 @@ +use dioxus::{nodes::VSuspended, prelude::*, DomEdit, TestDom}; +use dioxus_core as dioxus; +use dioxus_html as dioxus_elements; + +static Parent: FC<()> = |cx, props| { + // + let value = cx.use_hook(|_| String::new(), |f| &*f, |_| {}); + + cx.render(rsx! { + div { + Child { name: value } + Child { name: value } + Child { name: value } + Child { name: value } + } + }) +}; + +#[derive(Props)] +struct ChildProps<'a> { + name: &'a String, +} + +fn Child<'a>(cx: Context<'a>, props: &'a ChildProps) -> DomTree<'a> { + cx.render(rsx! { + div { + h1 { "it's nested" } + Child2 { name: props.name } + } + }) +} + +#[derive(Props)] +struct Grandchild<'a> { + name: &'a String, +} + +fn Child2<'a>(cx: Context<'a>, props: &Grandchild) -> DomTree<'a> { + cx.render(rsx! { + div { "Hello {props.name}!" } + }) +} + +#[test] +fn test_borrowed_state() {} diff --git a/packages/core/tests/create_dom.rs b/packages/core/tests/create_dom.rs index 124c87d66..b1b6639b8 100644 --- a/packages/core/tests/create_dom.rs +++ b/packages/core/tests/create_dom.rs @@ -18,7 +18,7 @@ fn new_dom(app: FC

, props: P) -> VirtualDom { #[test] fn test_original_diff() { - static APP: FC<()> = |cx| { + static APP: FC<()> = |cx, props| { cx.render(rsx! { div { div { @@ -48,7 +48,7 @@ fn test_original_diff() { #[test] fn create() { - static APP: FC<()> = |cx| { + static APP: FC<()> = |cx, props| { cx.render(rsx! { div { div { @@ -99,7 +99,7 @@ fn create() { #[test] fn create_list() { - static APP: FC<()> = |cx| { + static APP: FC<()> = |cx, props| { cx.render(rsx! { {(0..3).map(|f| rsx!{ div { "hello" @@ -139,7 +139,7 @@ fn create_list() { #[test] fn create_simple() { - static APP: FC<()> = |cx| { + static APP: FC<()> = |cx, props| { cx.render(rsx! { div {} div {} @@ -165,7 +165,7 @@ fn create_simple() { } #[test] fn create_components() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx! { Child { "abc1" } Child { "abc2" } @@ -173,7 +173,7 @@ fn create_components() { }) }; - static Child: FC<()> = |cx| { + static Child: FC<()> = |cx, props| { cx.render(rsx! { h1 {} div { {cx.children()} } @@ -217,7 +217,7 @@ fn create_components() { } #[test] fn anchors() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx! { {true.then(|| rsx!{ div { "hello" } })} {false.then(|| rsx!{ div { "goodbye" } })} @@ -243,7 +243,7 @@ fn anchors() { #[test] fn suspended() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { let val = use_suspense( cx, || async { diff --git a/packages/core/tests/display_vdom.rs b/packages/core/tests/display_vdom.rs index e2321585b..461a9068b 100644 --- a/packages/core/tests/display_vdom.rs +++ b/packages/core/tests/display_vdom.rs @@ -15,7 +15,7 @@ const IS_LOGGING_ENABLED: bool = true; #[test] fn please_work() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx! { div { hidden: "true" @@ -29,7 +29,7 @@ fn please_work() { }) }; - static Child: FC<()> = |cx| { + static Child: FC<()> = |cx, props| { cx.render(rsx! { div { "child" } }) diff --git a/packages/core/tests/eventsystem.rs b/packages/core/tests/eventsystem.rs index 9c7748e44..ccdd03810 100644 --- a/packages/core/tests/eventsystem.rs +++ b/packages/core/tests/eventsystem.rs @@ -7,7 +7,7 @@ use dioxus_html as dioxus_elements; #[async_std::test] async fn event_queue_works() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx! { div { "hello world" } }) diff --git a/packages/core/tests/lifecycle.rs b/packages/core/tests/lifecycle.rs index ad5a8b0f4..6faf8d9e4 100644 --- a/packages/core/tests/lifecycle.rs +++ b/packages/core/tests/lifecycle.rs @@ -20,8 +20,8 @@ fn manual_diffing() { value: Shared<&'static str>, } - static App: FC = |cx| { - let val = cx.value.borrow(); + static App: FC = |cx, props| { + let val = props.value.borrow(); cx.render(rsx! { div { "{val}" } }) }; diff --git a/packages/core/tests/sharedstate.rs b/packages/core/tests/sharedstate.rs index a5e2b1dad..b34980b64 100644 --- a/packages/core/tests/sharedstate.rs +++ b/packages/core/tests/sharedstate.rs @@ -15,12 +15,12 @@ fn new_dom() -> TestDom { fn shared_state_test() { struct MySharedState(&'static str); - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.use_provide_state(|| MySharedState("world!")); rsx!(cx, Child {}) }; - static Child: FC<()> = |cx| { + static Child: FC<()> = |cx, props| { let shared = cx.use_consume_state::()?; rsx!(cx, "Hello, {shared.0}") }; diff --git a/packages/core/tests/vdom_rebuild.rs b/packages/core/tests/vdom_rebuild.rs index 3cd985f11..13f30a0eb 100644 --- a/packages/core/tests/vdom_rebuild.rs +++ b/packages/core/tests/vdom_rebuild.rs @@ -14,7 +14,7 @@ use dioxus_html as dioxus_elements; #[test] fn app_runs() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { // cx.render(rsx!( div{"hello"} )) }; @@ -25,7 +25,7 @@ fn app_runs() { #[test] fn fragments_work() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx!( div{"hello"} div{"goodbye"} @@ -39,7 +39,7 @@ fn fragments_work() { #[test] fn lists_work() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx!( h1 {"hello"} {(0..6).map(|f| rsx!(span{ "{f}" }))} @@ -52,7 +52,7 @@ fn lists_work() { #[test] fn conditional_rendering() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx!( h1 {"hello"} {true.then(|| rsx!(span{ "a" }))} @@ -69,13 +69,13 @@ fn conditional_rendering() { #[test] fn child_components() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { cx.render(rsx!( {true.then(|| rsx!(Child { }))} {false.then(|| rsx!(Child { }))} )) }; - static Child: FC<()> = |cx| { + static Child: FC<()> = |cx, props| { cx.render(rsx!( h1 {"hello"} h1 {"goodbye"} @@ -88,7 +88,7 @@ fn child_components() { #[test] fn suspended_works() { - static App: FC<()> = |cx| { + static App: FC<()> = |cx, props| { let title = use_suspense(cx, || async { "bob" }, |cx, f| cx.render(rsx! { "{f}"})); cx.render(rsx!("hello" { title })) };