Procházet zdrojové kódy

feat: transition to cx, props

Jonathan Kelley před 3 roky
rodič
revize
bfdcb20

+ 1 - 1
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())))
 }
 

+ 8 - 9
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.

+ 7 - 10
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<Out>)
 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::<Out>().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<T, P>(cx: Context<P>) -> NodeRef<T> {
+pub fn use_node_ref<T, P>(cx: Context) -> NodeRef<T> {
     cx.use_hook(
         |f| {},
         |f| {

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

@@ -54,7 +54,7 @@ pub(crate) mod innerlude {
     pub use crate::virtual_dom::*;
 
     pub type DomTree<'a> = Option<VNode<'a>>;
-    pub type FC<P> = fn(Context<P>) -> DomTree;
+    pub type FC<P> = for<'a> fn(Context<'a>, &'a P) -> DomTree<'a>;
 
     pub use dioxus_core_macro::{format_args_f, html, rsx};
 }

+ 1 - 1
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) }
             });
 

+ 1 - 4
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();

+ 2 - 2
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<dyn Fn(&Scope) -> 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<dyn Fn(&Scope) -> 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(&[]));

+ 45 - 0
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() {}

+ 8 - 8
packages/core/tests/create_dom.rs

@@ -18,7 +18,7 @@ fn new_dom<P: Properties + 'static>(app: FC<P>, 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 {

+ 2 - 2
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" }
         })

+ 1 - 1
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" }
         })

+ 2 - 2
packages/core/tests/lifecycle.rs

@@ -20,8 +20,8 @@ fn manual_diffing() {
         value: Shared<&'static str>,
     }
 
-    static App: FC<AppProps> = |cx| {
-        let val = cx.value.borrow();
+    static App: FC<AppProps> = |cx, props| {
+        let val = props.value.borrow();
         cx.render(rsx! { div { "{val}" } })
     };
 

+ 2 - 2
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::<MySharedState>()?;
         rsx!(cx, "Hello, {shared.0}")
     };

+ 7 - 7
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 }))
     };